diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/CHANGELOG-v3.1.6.md b/CHANGELOG-v3.1.6.md old mode 100644 new mode 100755 diff --git a/Capture.png b/Capture.png old mode 100644 new mode 100755 diff --git a/HOWTO-PROKOV.md b/HOWTO-PROKOV.md old mode 100644 new mode 100755 diff --git a/MONITORING.md b/MONITORING.md old mode 100644 new mode 100755 diff --git a/PLANNING-STRIPE-ADMIN.md b/PLANNING-STRIPE-ADMIN.md old mode 100644 new mode 100755 diff --git a/VERSION b/VERSION old mode 100644 new mode 100755 index 1ac53bb4..b4b72c3d --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.6.3 \ No newline at end of file +26.01.2605 diff --git a/__MACOSX/geo-app-20251014/._pubspec.yaml b/__MACOSX/geo-app-20251014/._pubspec.yaml deleted file mode 100755 index f6878123..00000000 Binary files a/__MACOSX/geo-app-20251014/._pubspec.yaml and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/._ios b/__MACOSX/geo-app-20251014/build/._ios deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/._ios and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/._Release-iphoneos b/__MACOSX/geo-app-20251014/build/ios/._Release-iphoneos deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/._Release-iphoneos and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._Flutter b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._Flutter deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._Flutter and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._Stripe b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._Stripe deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._Stripe and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeApplePay b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeApplePay deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeApplePay and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeCore b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeCore deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeCore and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeFinancialConnections b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeFinancialConnections deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeFinancialConnections and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripePaymentSheet b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripePaymentSheet deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripePaymentSheet and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripePayments b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripePayments deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripePayments and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripePaymentsUI b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripePaymentsUI deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripePaymentsUI and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeTerminal b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeTerminal deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeTerminal and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeUICore b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeUICore deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._StripeUICore and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._battery_plus b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._battery_plus deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._battery_plus and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._connectivity_plus b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._connectivity_plus deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._connectivity_plus and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._device_info_plus b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._device_info_plus deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._device_info_plus and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._flutter_local_notifications b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._flutter_local_notifications deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._flutter_local_notifications and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._geolocator_apple b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._geolocator_apple deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._geolocator_apple and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._image_picker_ios b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._image_picker_ios deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._image_picker_ios and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._mek_stripe_terminal b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._mek_stripe_terminal deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._mek_stripe_terminal and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._nfc_manager b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._nfc_manager deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._nfc_manager and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._path_provider_foundation b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._path_provider_foundation deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._path_provider_foundation and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._permission_handler_apple b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._permission_handler_apple deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._permission_handler_apple and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._stripe_ios b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._stripe_ios deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._stripe_ios and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._url_launcher_ios b/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._url_launcher_ios deleted file mode 100755 index 69731abb..00000000 Binary files a/__MACOSX/geo-app-20251014/build/ios/Release-iphoneos/._url_launcher_ios and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/ios/._Runner.xcodeproj b/__MACOSX/geo-app-20251014/ios/._Runner.xcodeproj deleted file mode 100755 index d17f20a3..00000000 Binary files a/__MACOSX/geo-app-20251014/ios/._Runner.xcodeproj and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/ios/._Runner.xcworkspace b/__MACOSX/geo-app-20251014/ios/._Runner.xcworkspace deleted file mode 100755 index 75a1adbb..00000000 Binary files a/__MACOSX/geo-app-20251014/ios/._Runner.xcworkspace and /dev/null differ diff --git a/__MACOSX/geo-app-20251014/ios/Pods/._Pods.xcodeproj b/__MACOSX/geo-app-20251014/ios/Pods/._Pods.xcodeproj deleted file mode 100755 index 72fb2412..00000000 Binary files a/__MACOSX/geo-app-20251014/ios/Pods/._Pods.xcodeproj and /dev/null differ diff --git a/api/TODO-API.md b/api/TODO-API.md old mode 100644 new mode 100755 diff --git a/api/alter_table_geometry.sql b/api/alter_table_geometry.sql old mode 100644 new mode 100755 diff --git a/api/config/nginx/pra-geo-http-only.conf b/api/config/nginx/pra-geo-http-only.conf old mode 100644 new mode 100755 diff --git a/api/config/nginx/pra-geo-production.conf b/api/config/nginx/pra-geo-production.conf old mode 100644 new mode 100755 diff --git a/api/config/whitelist_ip_cache.txt b/api/config/whitelist_ip_cache.txt old mode 100644 new mode 100755 diff --git a/api/create_table_x_departements_contours.sql b/api/create_table_x_departements_contours.sql old mode 100644 new mode 100755 diff --git a/api/data/README.md b/api/data/README.md old mode 100644 new mode 100755 diff --git a/api/docs/API-SECURITY.md b/api/docs/API-SECURITY.md old mode 100644 new mode 100755 diff --git a/api/docs/CHAT_MODULE.md b/api/docs/CHAT_MODULE.md old mode 100644 new mode 100755 diff --git a/api/docs/CHK_USER_DELETE_PASS_INFO.md b/api/docs/CHK_USER_DELETE_PASS_INFO.md old mode 100644 new mode 100755 diff --git a/api/docs/DELETE_PASSAGE_PERMISSIONS.md b/api/docs/DELETE_PASSAGE_PERMISSIONS.md old mode 100644 new mode 100755 diff --git a/api/docs/EVENTS-LOG.md b/api/docs/EVENTS-LOG.md old mode 100644 new mode 100755 diff --git a/api/docs/FIX_USER_CREATION_400_ERRORS.md b/api/docs/FIX_USER_CREATION_400_ERRORS.md old mode 100644 new mode 100755 diff --git a/api/docs/GESTION-SECTORS.md b/api/docs/GESTION-SECTORS.md old mode 100644 new mode 100755 diff --git a/api/docs/INSTALL_FPDF.md b/api/docs/INSTALL_FPDF.md old mode 100644 new mode 100755 diff --git a/api/docs/PLANNING-STRIPE-API.md b/api/docs/PLANNING-STRIPE-API.md old mode 100644 new mode 100755 diff --git a/api/docs/PREPA_PROD.md b/api/docs/PREPA_PROD.md old mode 100644 new mode 100755 diff --git a/api/docs/SETUP_EMAIL_QUEUE_CRON.md b/api/docs/SETUP_EMAIL_QUEUE_CRON.md old mode 100644 new mode 100755 diff --git a/api/docs/STRIPE-BACKEND-MIGRATION.md b/api/docs/STRIPE-BACKEND-MIGRATION.md old mode 100644 new mode 100755 diff --git a/api/docs/STRIPE-TAP-TO-PAY-FLOW.md b/api/docs/STRIPE-TAP-TO-PAY-FLOW.md old mode 100644 new mode 100755 diff --git a/api/docs/STRIPE-TAP-TO-PAY-REQUIREMENTS.md b/api/docs/STRIPE-TAP-TO-PAY-REQUIREMENTS.md old mode 100644 new mode 100755 diff --git a/api/docs/STRIPE_VERIF.md b/api/docs/STRIPE_VERIF.md old mode 100644 new mode 100755 diff --git a/api/docs/UPLOAD-MIGRATION-RECAP.md b/api/docs/UPLOAD-MIGRATION-RECAP.md old mode 100644 new mode 100755 diff --git a/api/docs/UPLOAD-REORGANIZATION.md b/api/docs/UPLOAD-REORGANIZATION.md old mode 100644 new mode 100755 diff --git a/api/docs/USERNAME_VALIDATION_CHANGES.md b/api/docs/USERNAME_VALIDATION_CHANGES.md old mode 100644 new mode 100755 diff --git a/api/docs/_logo_recu.png b/api/docs/_logo_recu.png old mode 100644 new mode 100755 diff --git a/api/docs/_recu_template.pdf b/api/docs/_recu_template.pdf old mode 100644 new mode 100755 diff --git a/api/docs/contour-des-departements.geojson b/api/docs/contour-des-departements.geojson old mode 100644 new mode 100755 diff --git a/api/docs/create_table_user_devices.sql b/api/docs/create_table_user_devices.sql old mode 100644 new mode 100755 diff --git a/api/docs/departements_limitrophes.md b/api/docs/departements_limitrophes.md old mode 100644 new mode 100755 diff --git a/api/docs/logrotate_email_queue.conf b/api/docs/logrotate_email_queue.conf old mode 100644 new mode 100755 diff --git a/api/docs/nouvelles-routes-session-refresh.txt b/api/docs/nouvelles-routes-session-refresh.txt old mode 100644 new mode 100755 diff --git a/api/docs/recu_13718.pdf b/api/docs/recu_13718.pdf old mode 100644 new mode 100755 diff --git a/api/docs/recu_19500582.pdf b/api/docs/recu_19500582.pdf old mode 100644 new mode 100755 diff --git a/api/docs/recu_19500586.pdf b/api/docs/recu_19500586.pdf old mode 100644 new mode 100755 diff --git a/api/docs/recu_537254062.pdf b/api/docs/recu_537254062.pdf old mode 100644 new mode 100755 diff --git a/api/docs/recu_972506460.pdf b/api/docs/recu_972506460.pdf old mode 100644 new mode 100755 diff --git a/api/docs/traite_batiments.sql b/api/docs/traite_batiments.sql old mode 100644 new mode 100755 diff --git a/api/docs/x_departements_contours.sql b/api/docs/x_departements_contours.sql old mode 100644 new mode 100755 diff --git a/api/docs/x_departements_contours_corrected.sql b/api/docs/x_departements_contours_corrected.sql old mode 100644 new mode 100755 diff --git a/api/docs/x_departements_contours_fixed.sql b/api/docs/x_departements_contours_fixed.sql old mode 100644 new mode 100755 diff --git a/api/migration_add_departements_contours.sql b/api/migration_add_departements_contours.sql old mode 100644 new mode 100755 diff --git a/api/migration_add_sectors_adresses.sql b/api/migration_add_sectors_adresses.sql old mode 100644 new mode 100755 diff --git a/api/migrations/add_dept_limitrophes.sql b/api/migrations/add_dept_limitrophes.sql old mode 100644 new mode 100755 diff --git a/api/migrations/integrate_contours_to_departements.sql b/api/migrations/integrate_contours_to_departements.sql old mode 100644 new mode 100755 diff --git a/api/migrations/update_all_dept_limitrophes.sql b/api/migrations/update_all_dept_limitrophes.sql old mode 100644 new mode 100755 diff --git a/api/ralph b/api/ralph new file mode 160000 index 00000000..098579b5 --- /dev/null +++ b/api/ralph @@ -0,0 +1 @@ +Subproject commit 098579b5a124fa3c5e91e629fbc93a736bf3ccdf diff --git a/api/scripts/CORRECTIONS_MIGRATE.md b/api/scripts/CORRECTIONS_MIGRATE.md old mode 100644 new mode 100755 diff --git a/api/scripts/MIGRATION_PATCH_INSTRUCTIONS.md b/api/scripts/MIGRATION_PATCH_INSTRUCTIONS.md old mode 100644 new mode 100755 diff --git a/api/scripts/README-migration.md b/api/scripts/README-migration.md old mode 100644 new mode 100755 diff --git a/api/scripts/check_geometry_validity.sql b/api/scripts/check_geometry_validity.sql old mode 100644 new mode 100755 diff --git a/api/scripts/config/update_php_fpm_settings.sh b/api/scripts/config/update_php_fpm_settings.sh old mode 100644 new mode 100755 diff --git a/api/scripts/create_addresses_users.sql b/api/scripts/create_addresses_users.sql old mode 100644 new mode 100755 diff --git a/api/scripts/create_addresses_users_by_env.sql b/api/scripts/create_addresses_users_by_env.sql old mode 100644 new mode 100755 diff --git a/api/scripts/cron/CRON.md b/api/scripts/cron/CRON.md old mode 100644 new mode 100755 diff --git a/api/scripts/cron/cleanup_security_data.php b/api/scripts/cron/cleanup_security_data.php old mode 100644 new mode 100755 diff --git a/api/scripts/cron/process_email_queue_with_daily_log.sh b/api/scripts/cron/process_email_queue_with_daily_log.sh old mode 100644 new mode 100755 diff --git a/api/scripts/cron/rotate_event_logs.php b/api/scripts/cron/rotate_event_logs.php old mode 100644 new mode 100755 diff --git a/api/scripts/fix_geometry_for_spatial_index.sql b/api/scripts/fix_geometry_for_spatial_index.sql old mode 100644 new mode 100755 diff --git a/api/scripts/import_departements_from_file.php b/api/scripts/import_departements_from_file.php old mode 100644 new mode 100755 diff --git a/api/scripts/import_department_boundaries.php b/api/scripts/import_department_boundaries.php old mode 100644 new mode 100755 diff --git a/api/scripts/init_departements_contours.php b/api/scripts/init_departements_contours.php old mode 100644 new mode 100755 diff --git a/api/scripts/migrate_uploads_structure.php b/api/scripts/migrate_uploads_structure.php old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/README.md b/api/scripts/migration2/README.md old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/geo_app_structure.sql b/api/scripts/migration2/geo_app_structure.sql old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/geosector-structure.sql b/api/scripts/migration2/geosector-structure.sql old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/logs/.gitignore b/api/scripts/migration2/logs/.gitignore old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/php/lib/DataMigrator.php b/api/scripts/migration2/php/lib/DataMigrator.php old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/php/lib/DatabaseConfig.php b/api/scripts/migration2/php/lib/DatabaseConfig.php old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/php/lib/DatabaseConnection.php b/api/scripts/migration2/php/lib/DatabaseConnection.php old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/php/lib/MigrationLogger.php b/api/scripts/migration2/php/lib/MigrationLogger.php old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/php/lib/OperationMigrator.php b/api/scripts/migration2/php/lib/OperationMigrator.php old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/php/lib/PassageMigrator.php b/api/scripts/migration2/php/lib/PassageMigrator.php old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/php/lib/SectorMigrator.php b/api/scripts/migration2/php/lib/SectorMigrator.php old mode 100644 new mode 100755 diff --git a/api/scripts/migration2/php/lib/UserMigrator.php b/api/scripts/migration2/php/lib/UserMigrator.php old mode 100644 new mode 100755 diff --git a/api/scripts/migrations_entites.json b/api/scripts/migrations_entites.json old mode 100644 new mode 100755 diff --git a/api/scripts/orga/TODO-ISOLATION-OPERATIONS.md b/api/scripts/orga/TODO-ISOLATION-OPERATIONS.md old mode 100644 new mode 100755 diff --git a/api/scripts/orga/fix_fk_constraints.sql b/api/scripts/orga/fix_fk_constraints.sql old mode 100644 new mode 100755 diff --git a/api/scripts/orga/fix_fk_constraints_safe.sql b/api/scripts/orga/fix_fk_constraints_safe.sql old mode 100644 new mode 100755 diff --git a/api/scripts/orga/truncate_all_tables.sql b/api/scripts/orga/truncate_all_tables.sql old mode 100644 new mode 100755 diff --git a/api/scripts/orga/verify_isolation.sql b/api/scripts/orga/verify_isolation.sql old mode 100644 new mode 100755 diff --git a/api/scripts/patch_migration_scripts.sh b/api/scripts/patch_migration_scripts.sh old mode 100644 new mode 100755 diff --git a/api/scripts/php/init_security_tables.php b/api/scripts/php/init_security_tables.php old mode 100644 new mode 100755 diff --git a/api/scripts/php/verify_migration_structure.php b/api/scripts/php/verify_migration_structure.php old mode 100644 new mode 100755 diff --git a/api/scripts/setup_addresses_access.sh b/api/scripts/setup_addresses_access.sh old mode 100644 new mode 100755 diff --git a/api/scripts/setup_addresses_access_by_env.sh b/api/scripts/setup_addresses_access_by_env.sh old mode 100644 new mode 100755 diff --git a/api/scripts/sql/add_chk_user_delete_pass.sql b/api/scripts/sql/add_chk_user_delete_pass.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/add_chk_username_manuel.sql b/api/scripts/sql/add_chk_username_manuel.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/add_email_queue_fields.sql b/api/scripts/sql/add_email_queue_fields.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/add_unique_constraints_SIMPLE.sql b/api/scripts/sql/add_unique_constraints_SIMPLE.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/add_unique_constraints_ope_tables.sql b/api/scripts/sql/add_unique_constraints_ope_tables.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/add_unique_constraints_ope_tables_FAST.sql b/api/scripts/sql/add_unique_constraints_ope_tables_FAST.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/alter_ope_pass_fk_sector_default_null.sql b/api/scripts/sql/alter_ope_pass_fk_sector_default_null.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/create_chat_tables.sql b/api/scripts/sql/create_chat_tables.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/create_event_stats_daily.sql b/api/scripts/sql/create_event_stats_daily.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/create_security_tables.sql b/api/scripts/sql/create_security_tables.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/drop_stripe_devices_table.sql b/api/scripts/sql/drop_stripe_devices_table.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/migration_username_utf8_support.sql b/api/scripts/sql/migration_username_utf8_support.sql old mode 100644 new mode 100755 diff --git a/api/scripts/sql/truncate_data_tables.sql b/api/scripts/sql/truncate_data_tables.sql old mode 100644 new mode 100755 diff --git a/api/src/Controllers/ChatController.php b/api/src/Controllers/ChatController.php old mode 100644 new mode 100755 diff --git a/api/src/Controllers/EventStatsController.php b/api/src/Controllers/EventStatsController.php old mode 100644 new mode 100755 diff --git a/api/src/Controllers/HealthController.php b/api/src/Controllers/HealthController.php old mode 100644 new mode 100755 diff --git a/api/src/Controllers/MigrationController.php b/api/src/Controllers/MigrationController.php old mode 100644 new mode 100755 diff --git a/api/src/Controllers/PasswordController.php b/api/src/Controllers/PasswordController.php old mode 100644 new mode 100755 diff --git a/api/src/Controllers/SectorController.php b/api/src/Controllers/SectorController.php old mode 100644 new mode 100755 diff --git a/api/src/Controllers/SecurityController.php b/api/src/Controllers/SecurityController.php old mode 100644 new mode 100755 diff --git a/api/src/Controllers/StripeController.php b/api/src/Controllers/StripeController.php old mode 100644 new mode 100755 diff --git a/api/src/Controllers/StripeWebhookController.php b/api/src/Controllers/StripeWebhookController.php old mode 100644 new mode 100755 diff --git a/api/src/Controllers/UserController.php b/api/src/Controllers/UserController.php index bc5da00f..d7bbea08 100755 --- a/api/src/Controllers/UserController.php +++ b/api/src/Controllers/UserController.php @@ -503,15 +503,17 @@ class UserController { ]); $userId = $this->db->lastInsertId(); - // Récupérer l'opération active courante de l'admin créateur + // Récupérer l'opération active pour l'entité de l'admin créateur $stmtActiveOpe = $this->db->prepare(' - SELECT fk_operation - FROM users - WHERE id = ? AND chk_active = 1 + SELECT o.id + FROM operations o + INNER JOIN users u ON u.fk_entite = o.fk_entite + WHERE u.id = ? AND o.chk_active = 1 + LIMIT 1 '); $stmtActiveOpe->execute([$currentUserId]); $activeOpeData = $stmtActiveOpe->fetch(PDO::FETCH_ASSOC); - $activeOperationId = $activeOpeData ? (int)$activeOpeData['fk_operation'] : null; + $activeOperationId = $activeOpeData ? (int)$activeOpeData['id'] : null; $opeUserId = null; diff --git a/api/src/Core/AddressesDatabase.php b/api/src/Core/AddressesDatabase.php old mode 100644 new mode 100755 diff --git a/api/src/Core/Controller.php b/api/src/Core/Controller.php old mode 100644 new mode 100755 diff --git a/api/src/Core/MonitoredDatabase.php b/api/src/Core/MonitoredDatabase.php old mode 100644 new mode 100755 diff --git a/api/src/Services/AddressService.php b/api/src/Services/AddressService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/BuildingService.php b/api/src/Services/BuildingService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/DepartmentBoundaryService.php b/api/src/Services/DepartmentBoundaryService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/EventLogService.php b/api/src/Services/EventLogService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/EventStatsService.php b/api/src/Services/EventStatsService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/MigrationService.php b/api/src/Services/MigrationService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/PDFGenerator.php b/api/src/Services/PDFGenerator.php old mode 100644 new mode 100755 diff --git a/api/src/Services/PasswordSecurityService.php b/api/src/Services/PasswordSecurityService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/ReceiptPDFGenerator.php b/api/src/Services/ReceiptPDFGenerator.php old mode 100644 new mode 100755 diff --git a/api/src/Services/ReceiptService.php b/api/src/Services/ReceiptService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/SectorService.php b/api/src/Services/SectorService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/Security/AlertService.php b/api/src/Services/Security/AlertService.php old mode 100644 new mode 100755 diff --git a/api/src/Services/Security/EmailThrottler.php b/api/src/Services/Security/EmailThrottler.php old mode 100644 new mode 100755 diff --git a/api/src/Services/Security/IPBlocker.php b/api/src/Services/Security/IPBlocker.php old mode 100644 new mode 100755 diff --git a/api/src/Services/Security/PerformanceMonitor.php b/api/src/Services/Security/PerformanceMonitor.php old mode 100644 new mode 100755 diff --git a/api/src/Services/Security/SecurityMonitor.php b/api/src/Services/Security/SecurityMonitor.php old mode 100644 new mode 100755 diff --git a/api/src/Services/SimplePDF.php b/api/src/Services/SimplePDF.php old mode 100644 new mode 100755 diff --git a/api/src/Services/StripeService.php b/api/src/Services/StripeService.php old mode 100644 new mode 100755 diff --git a/api/test_addresses_connection.php b/api/test_addresses_connection.php old mode 100644 new mode 100755 diff --git a/api/test_addresses_dept.php b/api/test_addresses_dept.php old mode 100644 new mode 100755 diff --git a/api/test_api_geo.php b/api/test_api_geo.php old mode 100644 new mode 100755 diff --git a/api/test_chat_temp_id.php b/api/test_chat_temp_id.php old mode 100644 new mode 100755 diff --git a/api/test_departements_init.php b/api/test_departements_init.php old mode 100644 new mode 100755 diff --git a/api/test_import_diagnostic.php b/api/test_import_diagnostic.php old mode 100644 new mode 100755 diff --git a/api/test_import_errors.php b/api/test_import_errors.php old mode 100644 new mode 100755 diff --git a/api/test_sector_departments.php b/api/test_sector_departments.php old mode 100644 new mode 100755 diff --git a/api/test_security.php b/api/test_security.php old mode 100644 new mode 100755 diff --git a/api/test_stripe.php b/api/test_stripe.php old mode 100644 new mode 100755 diff --git a/api/test_stripe_simple.php b/api/test_stripe_simple.php old mode 100644 new mode 100755 diff --git a/api/vendor/autoload.php b/api/vendor/autoload.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/ClassLoader.php b/api/vendor/composer/ClassLoader.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/InstalledVersions.php b/api/vendor/composer/InstalledVersions.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/LICENSE b/api/vendor/composer/LICENSE old mode 100644 new mode 100755 diff --git a/api/vendor/composer/autoload_classmap.php b/api/vendor/composer/autoload_classmap.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/autoload_namespaces.php b/api/vendor/composer/autoload_namespaces.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/autoload_psr4.php b/api/vendor/composer/autoload_psr4.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/autoload_real.php b/api/vendor/composer/autoload_real.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/autoload_static.php b/api/vendor/composer/autoload_static.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/installed.json b/api/vendor/composer/installed.json old mode 100644 new mode 100755 diff --git a/api/vendor/composer/installed.php b/api/vendor/composer/installed.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/LICENSE b/api/vendor/composer/pcre/LICENSE old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/README.md b/api/vendor/composer/pcre/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/composer.json b/api/vendor/composer/pcre/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/extension.neon b/api/vendor/composer/pcre/extension.neon old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/MatchAllResult.php b/api/vendor/composer/pcre/src/MatchAllResult.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/MatchAllStrictGroupsResult.php b/api/vendor/composer/pcre/src/MatchAllStrictGroupsResult.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/MatchAllWithOffsetsResult.php b/api/vendor/composer/pcre/src/MatchAllWithOffsetsResult.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/MatchResult.php b/api/vendor/composer/pcre/src/MatchResult.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/MatchStrictGroupsResult.php b/api/vendor/composer/pcre/src/MatchStrictGroupsResult.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/MatchWithOffsetsResult.php b/api/vendor/composer/pcre/src/MatchWithOffsetsResult.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/PHPStan/InvalidRegexPatternRule.php b/api/vendor/composer/pcre/src/PHPStan/InvalidRegexPatternRule.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/PHPStan/PregMatchFlags.php b/api/vendor/composer/pcre/src/PHPStan/PregMatchFlags.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php b/api/vendor/composer/pcre/src/PHPStan/PregMatchParameterOutTypeExtension.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php b/api/vendor/composer/pcre/src/PHPStan/PregMatchTypeSpecifyingExtension.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/PHPStan/PregReplaceCallbackClosureTypeExtension.php b/api/vendor/composer/pcre/src/PHPStan/PregReplaceCallbackClosureTypeExtension.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php b/api/vendor/composer/pcre/src/PHPStan/UnsafeStrictGroupsCallRule.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/PcreException.php b/api/vendor/composer/pcre/src/PcreException.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/Preg.php b/api/vendor/composer/pcre/src/Preg.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/Regex.php b/api/vendor/composer/pcre/src/Regex.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/ReplaceResult.php b/api/vendor/composer/pcre/src/ReplaceResult.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/pcre/src/UnexpectedNullMatchException.php b/api/vendor/composer/pcre/src/UnexpectedNullMatchException.php old mode 100644 new mode 100755 diff --git a/api/vendor/composer/platform_check.php b/api/vendor/composer/platform_check.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/.editorconfig b/api/vendor/maennchen/zipstream-php/.editorconfig old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/.phive/phars.xml b/api/vendor/maennchen/zipstream-php/.phive/phars.xml old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php b/api/vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig b/api/vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/.tool-versions b/api/vendor/maennchen/zipstream-php/.tool-versions old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/LICENSE b/api/vendor/maennchen/zipstream-php/LICENSE old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/README.md b/api/vendor/maennchen/zipstream-php/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/composer.json b/api/vendor/maennchen/zipstream-php/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/guides/ContentLength.rst b/api/vendor/maennchen/zipstream-php/guides/ContentLength.rst old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/guides/FlySystem.rst b/api/vendor/maennchen/zipstream-php/guides/FlySystem.rst old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/guides/Nginx.rst b/api/vendor/maennchen/zipstream-php/guides/Nginx.rst old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/guides/Options.rst b/api/vendor/maennchen/zipstream-php/guides/Options.rst old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst b/api/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/guides/StreamOutput.rst b/api/vendor/maennchen/zipstream-php/guides/StreamOutput.rst old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/guides/Symfony.rst b/api/vendor/maennchen/zipstream-php/guides/Symfony.rst old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/guides/Varnish.rst b/api/vendor/maennchen/zipstream-php/guides/Varnish.rst old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/guides/index.rst b/api/vendor/maennchen/zipstream-php/guides/index.rst old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/phpdoc.dist.xml b/api/vendor/maennchen/zipstream-php/phpdoc.dist.xml old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/phpunit.xml.dist b/api/vendor/maennchen/zipstream-php/phpunit.xml.dist old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/psalm.xml b/api/vendor/maennchen/zipstream-php/psalm.xml old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php b/api/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/CompressionMethod.php b/api/vendor/maennchen/zipstream-php/src/CompressionMethod.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/DataDescriptor.php b/api/vendor/maennchen/zipstream-php/src/DataDescriptor.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/EndOfCentralDirectory.php b/api/vendor/maennchen/zipstream-php/src/EndOfCentralDirectory.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception.php b/api/vendor/maennchen/zipstream-php/src/Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception/DosTimeOverflowException.php b/api/vendor/maennchen/zipstream-php/src/Exception/DosTimeOverflowException.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception/FileNotFoundException.php b/api/vendor/maennchen/zipstream-php/src/Exception/FileNotFoundException.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception/FileNotReadableException.php b/api/vendor/maennchen/zipstream-php/src/Exception/FileNotReadableException.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception/FileSizeIncorrectException.php b/api/vendor/maennchen/zipstream-php/src/Exception/FileSizeIncorrectException.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception/OverflowException.php b/api/vendor/maennchen/zipstream-php/src/Exception/OverflowException.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception/ResourceActionException.php b/api/vendor/maennchen/zipstream-php/src/Exception/ResourceActionException.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php b/api/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php b/api/vendor/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Exception/StreamNotSeekableException.php b/api/vendor/maennchen/zipstream-php/src/Exception/StreamNotSeekableException.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/File.php b/api/vendor/maennchen/zipstream-php/src/File.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php b/api/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/LocalFileHeader.php b/api/vendor/maennchen/zipstream-php/src/LocalFileHeader.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/OperationMode.php b/api/vendor/maennchen/zipstream-php/src/OperationMode.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/PackField.php b/api/vendor/maennchen/zipstream-php/src/PackField.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Time.php b/api/vendor/maennchen/zipstream-php/src/Time.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Version.php b/api/vendor/maennchen/zipstream-php/src/Version.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Zip64/DataDescriptor.php b/api/vendor/maennchen/zipstream-php/src/Zip64/DataDescriptor.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectory.php b/api/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectory.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectoryLocator.php b/api/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectoryLocator.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Zip64/ExtendedInformationExtraField.php b/api/vendor/maennchen/zipstream-php/src/Zip64/ExtendedInformationExtraField.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/ZipStream.php b/api/vendor/maennchen/zipstream-php/src/ZipStream.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php b/api/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/Assertions.php b/api/vendor/maennchen/zipstream-php/test/Assertions.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php b/api/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php b/api/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php b/api/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php b/api/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php b/api/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php b/api/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/PackFieldTest.php b/api/vendor/maennchen/zipstream-php/test/PackFieldTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/ResourceStream.php b/api/vendor/maennchen/zipstream-php/test/ResourceStream.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/Tempfile.php b/api/vendor/maennchen/zipstream-php/test/Tempfile.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/TimeTest.php b/api/vendor/maennchen/zipstream-php/test/TimeTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/Util.php b/api/vendor/maennchen/zipstream-php/test/Util.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php b/api/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php b/api/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php b/api/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php b/api/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/ZipStreamTest.php b/api/vendor/maennchen/zipstream-php/test/ZipStreamTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php b/api/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/maennchen/zipstream-php/test/bootstrap.php b/api/vendor/maennchen/zipstream-php/test/bootstrap.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/.github/workflows/main.yml b/api/vendor/markbaker/complex/.github/workflows/main.yml old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/README.md b/api/vendor/markbaker/complex/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/classes/src/Complex.php b/api/vendor/markbaker/complex/classes/src/Complex.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/classes/src/Exception.php b/api/vendor/markbaker/complex/classes/src/Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/classes/src/Functions.php b/api/vendor/markbaker/complex/classes/src/Functions.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/classes/src/Operations.php b/api/vendor/markbaker/complex/classes/src/Operations.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/composer.json b/api/vendor/markbaker/complex/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/examples/complexTest.php b/api/vendor/markbaker/complex/examples/complexTest.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/examples/testFunctions.php b/api/vendor/markbaker/complex/examples/testFunctions.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/examples/testOperations.php b/api/vendor/markbaker/complex/examples/testOperations.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/complex/license.md b/api/vendor/markbaker/complex/license.md old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/.github/workflows/main.yaml b/api/vendor/markbaker/matrix/.github/workflows/main.yaml old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/README.md b/api/vendor/markbaker/matrix/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/buildPhar.php b/api/vendor/markbaker/matrix/buildPhar.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Builder.php b/api/vendor/markbaker/matrix/classes/src/Builder.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Decomposition/Decomposition.php b/api/vendor/markbaker/matrix/classes/src/Decomposition/Decomposition.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Decomposition/LU.php b/api/vendor/markbaker/matrix/classes/src/Decomposition/LU.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Decomposition/QR.php b/api/vendor/markbaker/matrix/classes/src/Decomposition/QR.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Div0Exception.php b/api/vendor/markbaker/matrix/classes/src/Div0Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Exception.php b/api/vendor/markbaker/matrix/classes/src/Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Functions.php b/api/vendor/markbaker/matrix/classes/src/Functions.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Matrix.php b/api/vendor/markbaker/matrix/classes/src/Matrix.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Operations.php b/api/vendor/markbaker/matrix/classes/src/Operations.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Operators/Addition.php b/api/vendor/markbaker/matrix/classes/src/Operators/Addition.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Operators/DirectSum.php b/api/vendor/markbaker/matrix/classes/src/Operators/DirectSum.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Operators/Division.php b/api/vendor/markbaker/matrix/classes/src/Operators/Division.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Operators/Multiplication.php b/api/vendor/markbaker/matrix/classes/src/Operators/Multiplication.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Operators/Operator.php b/api/vendor/markbaker/matrix/classes/src/Operators/Operator.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/classes/src/Operators/Subtraction.php b/api/vendor/markbaker/matrix/classes/src/Operators/Subtraction.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/composer.json b/api/vendor/markbaker/matrix/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/examples/test.php b/api/vendor/markbaker/matrix/examples/test.php old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/infection.json.dist b/api/vendor/markbaker/matrix/infection.json.dist old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/license.md b/api/vendor/markbaker/matrix/license.md old mode 100644 new mode 100755 diff --git a/api/vendor/markbaker/matrix/phpstan.neon b/api/vendor/markbaker/matrix/phpstan.neon old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/COMMITMENT b/api/vendor/phpmailer/phpmailer/COMMITMENT old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/LICENSE b/api/vendor/phpmailer/phpmailer/LICENSE old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/README.md b/api/vendor/phpmailer/phpmailer/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/SECURITY.md b/api/vendor/phpmailer/phpmailer/SECURITY.md old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/SMTPUTF8.md b/api/vendor/phpmailer/phpmailer/SMTPUTF8.md old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/VERSION b/api/vendor/phpmailer/phpmailer/VERSION old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/composer.json b/api/vendor/phpmailer/phpmailer/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/get_oauth_token.php b/api/vendor/phpmailer/phpmailer/get_oauth_token.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-af.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-af.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ar.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ar.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-as.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-as.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-az.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-az.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ba.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ba.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-be.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-be.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-bg.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-bg.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-bn.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-bn.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ca.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ca.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-cs.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-cs.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-da.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-de.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-de.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-el.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-el.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-eo.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-eo.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-es.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-es.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-et.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-et.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-fa.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-fa.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-fi.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-fi.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-fo.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-fo.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-fr.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-fr.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-gl.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-gl.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-he.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-he.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-hi.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-hi.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-hr.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-hr.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-hu.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-hu.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-hy.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-hy.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-id.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-id.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-it.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-it.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ja.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ja.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ka.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ka.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ko.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ko.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ku.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ku.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-lt.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-lt.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-lv.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-lv.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-mg.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-mg.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-mn.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-mn.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ms.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ms.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-nb.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-nb.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-nl.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-nl.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-pl.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-pl.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-pt_br.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ro.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ro.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ru.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-si.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-si.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sk.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sk.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sl.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sl.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sr.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sr.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sr_latn.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sr_latn.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sv.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-sv.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-tl.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-tl.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-tr.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-tr.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-uk.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ur.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-ur.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-vi.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-vi.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-zh.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-zh.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-zh_cn.php b/api/vendor/phpmailer/phpmailer/language/phpmailer.lang-zh_cn.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/src/DSNConfigurator.php b/api/vendor/phpmailer/phpmailer/src/DSNConfigurator.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/src/Exception.php b/api/vendor/phpmailer/phpmailer/src/Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/src/OAuth.php b/api/vendor/phpmailer/phpmailer/src/OAuth.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/src/OAuthTokenProvider.php b/api/vendor/phpmailer/phpmailer/src/OAuthTokenProvider.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/src/PHPMailer.php b/api/vendor/phpmailer/phpmailer/src/PHPMailer.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/src/POP3.php b/api/vendor/phpmailer/phpmailer/src/POP3.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpmailer/phpmailer/src/SMTP.php b/api/vendor/phpmailer/phpmailer/src/SMTP.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/CHANGELOG.md b/api/vendor/phpoffice/phpspreadsheet/CHANGELOG.md old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md b/api/vendor/phpoffice/phpspreadsheet/CONTRIBUTING.md old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/LICENSE b/api/vendor/phpoffice/phpspreadsheet/LICENSE old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/README.md b/api/vendor/phpoffice/phpspreadsheet/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/composer.json b/api/vendor/phpoffice/phpspreadsheet/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/ArrayEnabled.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/ArrayEnabled.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/BinaryComparison.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/BinaryComparison.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Calculation.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Category.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Category.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DAverage.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DAverage.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DCount.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DCount.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DCountA.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DCountA.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DGet.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DGet.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DMax.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DMax.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DMin.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DMin.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DProduct.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DProduct.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DStDev.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DStDev.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DStDevP.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DStDevP.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DSum.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DSum.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DVar.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DVar.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DVarP.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DVarP.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DatabaseAbstract.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Database/DatabaseAbstract.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Constants.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Constants.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Current.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Current.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Date.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Date.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateParts.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateParts.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateValue.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Days.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Days.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Days360.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Days360.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Difference.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Difference.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Helpers.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Helpers.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Time.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Time.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeParts.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeParts.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Week.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/Week.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/ArrayArgumentHelper.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/ArrayArgumentHelper.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/ArrayArgumentProcessor.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/ArrayArgumentProcessor.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/BranchPruner.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/BranchPruner.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/CyclicReferenceStack.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/CyclicReferenceStack.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Logger.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Logger.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/Operand.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/Operand.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engine/Operands/StructuredReference.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselI.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselI.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselJ.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselJ.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselK.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselK.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselY.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BesselY.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BitWise.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/BitWise.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Compare.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Compare.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Complex.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ComplexFunctions.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ComplexFunctions.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ComplexOperations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ComplexOperations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Constants.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Constants.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBase.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBase.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertBinary.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertDecimal.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertDecimal.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertHex.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertHex.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertOctal.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertOctal.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ConvertUOM.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/EngineeringValidations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/EngineeringValidations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Erf.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/Erf.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ErfC.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Engineering/ErfC.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Exception.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/ExceptionHandler.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/ExceptionHandler.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Amortization.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Amortization.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/CashFlowValidations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/CashFlowValidations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Cumulative.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Cumulative.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Interest.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/InterestAndPrincipal.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/InterestAndPrincipal.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Payments.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Constant/Periodic/Payments.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Single.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Single.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/NonPeriodic.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/NonPeriodic.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/Periodic.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/CashFlow/Variable/Periodic.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Constants.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Constants.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Coupons.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Coupons.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Depreciation.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Depreciation.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Dollar.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Dollar.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/FinancialValidations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/FinancialValidations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Helpers.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Helpers.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/InterestRate.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/InterestRate.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/AccruedInterest.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/AccruedInterest.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Rates.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Rates.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/SecurityValidations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/SecurityValidations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/TreasuryBill.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Financial/TreasuryBill.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/FormulaParser.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/FormulaParser.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/FormulaToken.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/FormulaToken.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Functions.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/ErrorValue.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/ErrorValue.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/ExcelError.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/ExcelError.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/Value.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Information/Value.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Internal/MakeMatrix.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Internal/MakeMatrix.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Internal/WildcardMatch.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Internal/WildcardMatch.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Boolean.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Boolean.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Conditional.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Conditional.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Operations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Logical/Operations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Address.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Address.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/ExcelMatch.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/ExcelMatch.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Filter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Filter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Formula.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Formula.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/HLookup.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Helpers.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Helpers.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Hyperlink.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Hyperlink.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Indirect.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Lookup.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Lookup.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/LookupBase.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/LookupBase.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/LookupRefValidations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/LookupRefValidations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Matrix.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Offset.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Offset.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/RowColumnInformation.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Selection.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Selection.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Sort.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Sort.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Unique.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/Unique.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/LookupRef/VLookup.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Absolute.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Absolute.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Angle.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Angle.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Arabic.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Arabic.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Base.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Base.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Ceiling.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Ceiling.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Combinations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Exp.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Exp.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Factorial.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Factorial.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Floor.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Floor.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Gcd.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Gcd.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Helpers.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Helpers.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/IntClass.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/IntClass.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Lcm.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Lcm.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Logarithms.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Logarithms.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/MatrixFunctions.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/MatrixFunctions.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Operations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Operations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Random.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Random.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Roman.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Roman.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Round.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Round.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/SeriesSum.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/SeriesSum.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sign.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sign.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sqrt.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sqrt.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Subtotal.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Subtotal.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Sum.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/SumSquares.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/SumSquares.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Cosecant.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Cosecant.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Cosine.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Cosine.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Cotangent.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Cotangent.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Secant.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Secant.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Sine.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Sine.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Tangent.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trig/Tangent.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trunc.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/MathTrig/Trunc.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/AggregateBase.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/AggregateBase.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Averages.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Averages.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Averages/Mean.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Averages/Mean.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Conditional.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Confidence.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Confidence.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Counts.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Counts.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Deviations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Deviations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Beta.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Binomial.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Binomial.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/ChiSquared.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/DistributionValidations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/DistributionValidations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Exponential.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Exponential.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/F.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/F.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Fisher.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Fisher.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Gamma.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Gamma.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/GammaBase.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/HyperGeometric.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/HyperGeometric.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/LogNormal.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/LogNormal.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/NewtonRaphson.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/NewtonRaphson.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Normal.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Poisson.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Poisson.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StandardNormal.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StandardNormal.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StudentT.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/StudentT.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Weibull.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Distributions/Weibull.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/MaxMinBase.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Maximum.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Maximum.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Minimum.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Minimum.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Percentiles.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Percentiles.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Permutations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Size.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Size.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/StandardDeviations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/StandardDeviations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Standardize.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Standardize.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/StatisticalValidations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/StatisticalValidations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Trends.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Trends.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/VarianceBase.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Variances.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Statistical/Variances.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/CaseConvert.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/CaseConvert.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/CharacterConvert.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Concatenate.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Concatenate.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Extract.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Format.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Helpers.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Helpers.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Replace.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Replace.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Search.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Search.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Text.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Trim.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/TextData/Trim.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Token/Stack.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Token/Stack.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Web/Service.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/Web/Service.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/Translations.xlsx b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/Translations.xlsx old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/bg/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/bg/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/bg/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/bg/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/cs/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/cs/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/cs/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/cs/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/da/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/da/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/da/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/da/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/de/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/de/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/de/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/de/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/en/uk/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/en/uk/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/es/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/es/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/es/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/es/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/fi/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/fi/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/fi/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/fi/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/fr/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/fr/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/fr/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/fr/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/hu/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/hu/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/hu/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/hu/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/it/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/it/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/it/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/it/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/nb/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/nb/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/nb/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/nb/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/nl/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/nl/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/nl/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/nl/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pl/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pl/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pl/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pl/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pt/br/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pt/br/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pt/br/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pt/br/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pt/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pt/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pt/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/pt/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/ru/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/ru/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/ru/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/ru/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/sv/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/sv/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/sv/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/sv/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/tr/config b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/tr/config old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/tr/functions b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Calculation/locale/tr/functions old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AddressHelper.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AddressHelper.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AddressRange.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AddressRange.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/AdvancedValueBinder.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Cell.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/CellAddress.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/CellAddress.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/CellRange.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/CellRange.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/ColumnRange.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/ColumnRange.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Coordinate.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataType.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataType.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidation.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidation.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DataValidator.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DefaultValueBinder.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/DefaultValueBinder.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Hyperlink.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/Hyperlink.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IValueBinder.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IValueBinder.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IgnoredErrors.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/IgnoredErrors.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/RowRange.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/RowRange.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/StringValueBinder.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Cell/StringValueBinder.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/CellReferenceHelper.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Axis.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/AxisText.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/AxisText.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Chart.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/ChartColor.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/ChartColor.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeries.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeries.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeriesValues.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/DataSeriesValues.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Exception.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/GridLines.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/GridLines.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Layout.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Legend.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/PlotArea.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Properties.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Properties.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/IRenderer.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/IRenderer.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraph.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/JpGraphRendererBase.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/MtJpGraphRenderer.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/PHP Charting Libraries.txt b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Renderer/PHP Charting Libraries.txt old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/Title.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/TrendLine.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Chart/TrendLine.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/Cells.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/Cells.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/CellsFactory.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/CellsFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/Memory/SimpleCache1.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/Memory/SimpleCache1.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/Memory/SimpleCache3.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Collection/Memory/SimpleCache3.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Comment.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Comment.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/DefinedName.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/DefinedName.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Properties.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Security.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Document/Security.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Exception.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/HashTable.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/HashTable.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Dimension.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Dimension.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Downloader.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Downloader.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Handler.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Handler.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Html.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Html.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Sample.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Size.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/Size.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Helper/TextGrid.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IComparable.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IComparable.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/IOFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/NamedFormula.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/NamedFormula.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/NamedRange.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/NamedRange.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/BaseReader.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/BaseReader.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv/Delimiter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Csv/Delimiter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/DefaultReadFilter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/DefaultReadFilter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Exception.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/PageSetup.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/PageSetup.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/Properties.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/Properties.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/Styles.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Gnumeric/Styles.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Html.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/IReadFilter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/IReadFilter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/IReader.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/IReader.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/AutoFilter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/AutoFilter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/BaseLoader.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/BaseLoader.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/DefinedNames.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/DefinedNames.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/FormulaTranslator.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/FormulaTranslator.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/PageSettings.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/PageSettings.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Ods/Properties.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Security/XmlScanner.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Slk.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Slk.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Color.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Color.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Color/BIFF5.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Color/BIFF5.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Color/BIFF8.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Color/BIFF8.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Color/BuiltIn.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Color/BuiltIn.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/ConditionalFormatting.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/ConditionalFormatting.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/DataValidationHelper.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/DataValidationHelper.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/ErrorCode.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Escher.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Escher.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/MD5.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/MD5.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/RC4.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/RC4.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Style/Border.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Style/Border.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Style/CellAlignment.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Style/CellAlignment.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Style/CellFont.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Style/CellFont.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Style/FillPattern.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xls/Style/FillPattern.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/AutoFilter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/BaseParserClass.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/BaseParserClass.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Chart.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ColumnAndRowAttributes.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ColumnAndRowAttributes.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/ConditionalStyles.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/DataValidations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Hyperlinks.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Hyperlinks.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Namespaces.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Namespaces.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/PageSetup.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Properties.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SharedFormula.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SharedFormula.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SheetViewOptions.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SheetViewOptions.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/SheetViews.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Styles.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/TableReader.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/TableReader.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Theme.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/Theme.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/WorkbookView.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xlsx/WorkbookView.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/DataValidations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/DataValidations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/PageSettings.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Properties.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Alignment.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Alignment.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Border.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Border.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Fill.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Fill.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/Font.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/NumberFormat.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/NumberFormat.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/StyleBase.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Reader/Xml/Style/StyleBase.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/ReferenceHelper.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/ITextElement.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/ITextElement.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/RichText.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/RichText.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/Run.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/RichText/TextElement.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Settings.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/CodePage.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/CodePage.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Date.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Drawing.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Drawing.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer/SpgrContainer.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer/SpgrContainer.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/File.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Font.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/IntOrFloat.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/IntOrFloat.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/ChainedBlockStream.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/File.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/File.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLE/PPS/Root.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/OLERead.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/PasswordHasher.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/PasswordHasher.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/StringHelper.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/TimeZone.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/TimeZone.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/BestFit.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/BestFit.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/ExponentialBestFit.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/ExponentialBestFit.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/LinearBestFit.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/LinearBestFit.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/LogarithmicBestFit.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/LogarithmicBestFit.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/PolynomialBestFit.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/PowerBestFit.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/PowerBestFit.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Trend/Trend.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/XMLWriter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/XMLWriter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Shared/Xls.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Spreadsheet.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Alignment.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Alignment.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Border.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Borders.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Color.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Conditional.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/CellMatcher.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/CellMatcher.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/CellStyleAssessor.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/CellStyleAssessor.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalColorScale.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalColorScale.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBar.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalDataBarExtension.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormatValueObject.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/ConditionalFormattingRuleExtension.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/StyleMerger.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/StyleMerger.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Blanks.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Blanks.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/CellValue.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/CellValue.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/DateValue.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/DateValue.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Duplicates.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Duplicates.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Errors.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Errors.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Expression.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Expression.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/TextValue.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/TextValue.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/WizardAbstract.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/WizardAbstract.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/WizardInterface.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/WizardInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Fill.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Fill.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Font.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/BaseFormatter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/BaseFormatter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/DateFormatter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/DateFormatter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Formatter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/FractionFormatter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/FractionFormatter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/NumberFormatter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/PercentageFormatter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Accounting.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Currency.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Date.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Date.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTime.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTime.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTimeWizard.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/DateTimeWizard.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Duration.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Duration.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Locale.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Number.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Number.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/NumberBase.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/NumberBase.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Percentage.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Percentage.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Scientific.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Scientific.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Time.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Time.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Wizard.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/NumberFormat/Wizard/Wizard.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Protection.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Protection.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/RgbTint.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/RgbTint.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Style.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Supervisor.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Style/Supervisor.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Theme.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Theme.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFilter/Column/Rule.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFit.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/AutoFit.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/BaseDrawing.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/BaseDrawing.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/CellIterator.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/CellIterator.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Column.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Column.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnCellIterator.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnDimension.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnDimension.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnIterator.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ColumnIterator.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Dimension.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Dimension.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing/Shadow.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Drawing/Shadow.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/HeaderFooter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/HeaderFooter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/HeaderFooterDrawing.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/HeaderFooterDrawing.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Iterator.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Iterator.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/MemoryDrawing.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/MemoryDrawing.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageBreak.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageBreak.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageMargins.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/PageSetup.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Pane.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Pane.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ProtectedRange.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/ProtectedRange.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Protection.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Protection.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Row.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Row.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowCellIterator.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowCellIterator.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowDimension.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowDimension.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowIterator.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowIterator.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/SheetView.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/Column.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/Column.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/TableStyle.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Table/TableStyle.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Validations.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Validations.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/Worksheet.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/BaseWriter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/BaseWriter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Csv.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Csv.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Exception.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Exception.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Html.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/IWriter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/IWriter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/AutoFilters.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/AutoFilters.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Cell/Comment.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Cell/Comment.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Cell/Style.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Cell/Style.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Content.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Formula.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Formula.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Meta.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Meta.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/MetaInf.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/MetaInf.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Mimetype.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Mimetype.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/NamedExpressions.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/NamedExpressions.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Settings.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Settings.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Styles.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Styles.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Thumbnails.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/Thumbnails.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/WriterPart.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Ods/WriterPart.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Dompdf.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Dompdf.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Mpdf.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Mpdf.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Pdf/Tcpdf.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/BIFFwriter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/BIFFwriter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/CellDataValidation.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/CellDataValidation.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/ConditionalHelper.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/ConditionalHelper.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/ErrorCode.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/ErrorCode.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Escher.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Escher.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Font.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Font.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Parser.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellAlignment.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellAlignment.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellBorder.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellBorder.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellFill.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Style/CellFill.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Workbook.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Workbook.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Worksheet.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Xf.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xls/Xf.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/AutoFilter.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/AutoFilter.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Chart.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Comments.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DefinedNames.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DefinedNames.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/DocProps.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/FunctionPrefix.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/FunctionPrefix.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Rels.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Rels.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsRibbon.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsRibbon.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsVBA.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/RelsVBA.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/StringTable.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Style.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Table.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Table.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Theme.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Workbook.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Worksheet.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/WriterPart.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/WriterPart.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream0.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream0.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream2.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream2.php old mode 100644 new mode 100755 diff --git a/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream3.php b/api/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/ZipStream3.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-client/CHANGELOG.md b/api/vendor/psr/http-client/CHANGELOG.md old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-client/LICENSE b/api/vendor/psr/http-client/LICENSE old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-client/README.md b/api/vendor/psr/http-client/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-client/composer.json b/api/vendor/psr/http-client/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-client/src/ClientExceptionInterface.php b/api/vendor/psr/http-client/src/ClientExceptionInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-client/src/ClientInterface.php b/api/vendor/psr/http-client/src/ClientInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-client/src/NetworkExceptionInterface.php b/api/vendor/psr/http-client/src/NetworkExceptionInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-client/src/RequestExceptionInterface.php b/api/vendor/psr/http-client/src/RequestExceptionInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-factory/LICENSE b/api/vendor/psr/http-factory/LICENSE old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-factory/README.md b/api/vendor/psr/http-factory/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-factory/composer.json b/api/vendor/psr/http-factory/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-factory/src/RequestFactoryInterface.php b/api/vendor/psr/http-factory/src/RequestFactoryInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-factory/src/ResponseFactoryInterface.php b/api/vendor/psr/http-factory/src/ResponseFactoryInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php b/api/vendor/psr/http-factory/src/ServerRequestFactoryInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-factory/src/StreamFactoryInterface.php b/api/vendor/psr/http-factory/src/StreamFactoryInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php b/api/vendor/psr/http-factory/src/UploadedFileFactoryInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-factory/src/UriFactoryInterface.php b/api/vendor/psr/http-factory/src/UriFactoryInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/CHANGELOG.md b/api/vendor/psr/http-message/CHANGELOG.md old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/LICENSE b/api/vendor/psr/http-message/LICENSE old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/README.md b/api/vendor/psr/http-message/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/composer.json b/api/vendor/psr/http-message/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/docs/PSR7-Interfaces.md b/api/vendor/psr/http-message/docs/PSR7-Interfaces.md old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/docs/PSR7-Usage.md b/api/vendor/psr/http-message/docs/PSR7-Usage.md old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/src/MessageInterface.php b/api/vendor/psr/http-message/src/MessageInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/src/RequestInterface.php b/api/vendor/psr/http-message/src/RequestInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/src/ResponseInterface.php b/api/vendor/psr/http-message/src/ResponseInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/src/ServerRequestInterface.php b/api/vendor/psr/http-message/src/ServerRequestInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/src/StreamInterface.php b/api/vendor/psr/http-message/src/StreamInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/src/UploadedFileInterface.php b/api/vendor/psr/http-message/src/UploadedFileInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/http-message/src/UriInterface.php b/api/vendor/psr/http-message/src/UriInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/simple-cache/.editorconfig b/api/vendor/psr/simple-cache/.editorconfig old mode 100644 new mode 100755 diff --git a/api/vendor/psr/simple-cache/LICENSE.md b/api/vendor/psr/simple-cache/LICENSE.md old mode 100644 new mode 100755 diff --git a/api/vendor/psr/simple-cache/README.md b/api/vendor/psr/simple-cache/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/psr/simple-cache/composer.json b/api/vendor/psr/simple-cache/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/psr/simple-cache/src/CacheException.php b/api/vendor/psr/simple-cache/src/CacheException.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/simple-cache/src/CacheInterface.php b/api/vendor/psr/simple-cache/src/CacheInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/psr/simple-cache/src/InvalidArgumentException.php b/api/vendor/psr/simple-cache/src/InvalidArgumentException.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/FAQ.htm b/api/vendor/setasign/fpdf/FAQ.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/README.md b/api/vendor/setasign/fpdf/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/changelog.htm b/api/vendor/setasign/fpdf/changelog.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/composer.json b/api/vendor/setasign/fpdf/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/__construct.htm b/api/vendor/setasign/fpdf/doc/__construct.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/acceptpagebreak.htm b/api/vendor/setasign/fpdf/doc/acceptpagebreak.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/addfont.htm b/api/vendor/setasign/fpdf/doc/addfont.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/addlink.htm b/api/vendor/setasign/fpdf/doc/addlink.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/addpage.htm b/api/vendor/setasign/fpdf/doc/addpage.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/aliasnbpages.htm b/api/vendor/setasign/fpdf/doc/aliasnbpages.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/cell.htm b/api/vendor/setasign/fpdf/doc/cell.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/close.htm b/api/vendor/setasign/fpdf/doc/close.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/error.htm b/api/vendor/setasign/fpdf/doc/error.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/footer.htm b/api/vendor/setasign/fpdf/doc/footer.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/getpageheight.htm b/api/vendor/setasign/fpdf/doc/getpageheight.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/getpagewidth.htm b/api/vendor/setasign/fpdf/doc/getpagewidth.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/getstringwidth.htm b/api/vendor/setasign/fpdf/doc/getstringwidth.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/getx.htm b/api/vendor/setasign/fpdf/doc/getx.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/gety.htm b/api/vendor/setasign/fpdf/doc/gety.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/header.htm b/api/vendor/setasign/fpdf/doc/header.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/image.htm b/api/vendor/setasign/fpdf/doc/image.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/index.htm b/api/vendor/setasign/fpdf/doc/index.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/line.htm b/api/vendor/setasign/fpdf/doc/line.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/link.htm b/api/vendor/setasign/fpdf/doc/link.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/ln.htm b/api/vendor/setasign/fpdf/doc/ln.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/multicell.htm b/api/vendor/setasign/fpdf/doc/multicell.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/output.htm b/api/vendor/setasign/fpdf/doc/output.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/pageno.htm b/api/vendor/setasign/fpdf/doc/pageno.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/rect.htm b/api/vendor/setasign/fpdf/doc/rect.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setauthor.htm b/api/vendor/setasign/fpdf/doc/setauthor.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setautopagebreak.htm b/api/vendor/setasign/fpdf/doc/setautopagebreak.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setcompression.htm b/api/vendor/setasign/fpdf/doc/setcompression.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setcreator.htm b/api/vendor/setasign/fpdf/doc/setcreator.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setdisplaymode.htm b/api/vendor/setasign/fpdf/doc/setdisplaymode.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setdrawcolor.htm b/api/vendor/setasign/fpdf/doc/setdrawcolor.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setfillcolor.htm b/api/vendor/setasign/fpdf/doc/setfillcolor.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setfont.htm b/api/vendor/setasign/fpdf/doc/setfont.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setfontsize.htm b/api/vendor/setasign/fpdf/doc/setfontsize.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setkeywords.htm b/api/vendor/setasign/fpdf/doc/setkeywords.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setleftmargin.htm b/api/vendor/setasign/fpdf/doc/setleftmargin.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setlinewidth.htm b/api/vendor/setasign/fpdf/doc/setlinewidth.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setlink.htm b/api/vendor/setasign/fpdf/doc/setlink.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setmargins.htm b/api/vendor/setasign/fpdf/doc/setmargins.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setrightmargin.htm b/api/vendor/setasign/fpdf/doc/setrightmargin.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setsubject.htm b/api/vendor/setasign/fpdf/doc/setsubject.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/settextcolor.htm b/api/vendor/setasign/fpdf/doc/settextcolor.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/settitle.htm b/api/vendor/setasign/fpdf/doc/settitle.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/settopmargin.htm b/api/vendor/setasign/fpdf/doc/settopmargin.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setx.htm b/api/vendor/setasign/fpdf/doc/setx.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/setxy.htm b/api/vendor/setasign/fpdf/doc/setxy.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/sety.htm b/api/vendor/setasign/fpdf/doc/sety.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/text.htm b/api/vendor/setasign/fpdf/doc/text.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/doc/write.htm b/api/vendor/setasign/fpdf/doc/write.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/courier.php b/api/vendor/setasign/fpdf/font/courier.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/courierb.php b/api/vendor/setasign/fpdf/font/courierb.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/courierbi.php b/api/vendor/setasign/fpdf/font/courierbi.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/courieri.php b/api/vendor/setasign/fpdf/font/courieri.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/helvetica.php b/api/vendor/setasign/fpdf/font/helvetica.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/helveticab.php b/api/vendor/setasign/fpdf/font/helveticab.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/helveticabi.php b/api/vendor/setasign/fpdf/font/helveticabi.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/helveticai.php b/api/vendor/setasign/fpdf/font/helveticai.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/symbol.php b/api/vendor/setasign/fpdf/font/symbol.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/times.php b/api/vendor/setasign/fpdf/font/times.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/timesb.php b/api/vendor/setasign/fpdf/font/timesb.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/timesbi.php b/api/vendor/setasign/fpdf/font/timesbi.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/timesi.php b/api/vendor/setasign/fpdf/font/timesi.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/font/zapfdingbats.php b/api/vendor/setasign/fpdf/font/zapfdingbats.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/fpdf.css b/api/vendor/setasign/fpdf/fpdf.css old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/fpdf.php b/api/vendor/setasign/fpdf/fpdf.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/install.txt b/api/vendor/setasign/fpdf/install.txt old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/license.txt b/api/vendor/setasign/fpdf/license.txt old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/cp1250.map b/api/vendor/setasign/fpdf/makefont/cp1250.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/cp1251.map b/api/vendor/setasign/fpdf/makefont/cp1251.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/cp1252.map b/api/vendor/setasign/fpdf/makefont/cp1252.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/cp1253.map b/api/vendor/setasign/fpdf/makefont/cp1253.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/cp1254.map b/api/vendor/setasign/fpdf/makefont/cp1254.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/cp1255.map b/api/vendor/setasign/fpdf/makefont/cp1255.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/cp1257.map b/api/vendor/setasign/fpdf/makefont/cp1257.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/cp1258.map b/api/vendor/setasign/fpdf/makefont/cp1258.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/cp874.map b/api/vendor/setasign/fpdf/makefont/cp874.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/iso-8859-1.map b/api/vendor/setasign/fpdf/makefont/iso-8859-1.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/iso-8859-11.map b/api/vendor/setasign/fpdf/makefont/iso-8859-11.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/iso-8859-15.map b/api/vendor/setasign/fpdf/makefont/iso-8859-15.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/iso-8859-16.map b/api/vendor/setasign/fpdf/makefont/iso-8859-16.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/iso-8859-2.map b/api/vendor/setasign/fpdf/makefont/iso-8859-2.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/iso-8859-4.map b/api/vendor/setasign/fpdf/makefont/iso-8859-4.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/iso-8859-5.map b/api/vendor/setasign/fpdf/makefont/iso-8859-5.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/iso-8859-7.map b/api/vendor/setasign/fpdf/makefont/iso-8859-7.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/iso-8859-9.map b/api/vendor/setasign/fpdf/makefont/iso-8859-9.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/koi8-r.map b/api/vendor/setasign/fpdf/makefont/koi8-r.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/koi8-u.map b/api/vendor/setasign/fpdf/makefont/koi8-u.map old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/makefont.php b/api/vendor/setasign/fpdf/makefont/makefont.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/makefont/ttfparser.php b/api/vendor/setasign/fpdf/makefont/ttfparser.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/20k_c1.txt b/api/vendor/setasign/fpdf/tutorial/20k_c1.txt old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/20k_c2.txt b/api/vendor/setasign/fpdf/tutorial/20k_c2.txt old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/CevicheOne-Regular-Licence.txt b/api/vendor/setasign/fpdf/tutorial/CevicheOne-Regular-Licence.txt old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/CevicheOne-Regular.php b/api/vendor/setasign/fpdf/tutorial/CevicheOne-Regular.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/CevicheOne-Regular.ttf b/api/vendor/setasign/fpdf/tutorial/CevicheOne-Regular.ttf old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/CevicheOne-Regular.z b/api/vendor/setasign/fpdf/tutorial/CevicheOne-Regular.z old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/countries.txt b/api/vendor/setasign/fpdf/tutorial/countries.txt old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/index.htm b/api/vendor/setasign/fpdf/tutorial/index.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/logo.png b/api/vendor/setasign/fpdf/tutorial/logo.png old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/makefont.php b/api/vendor/setasign/fpdf/tutorial/makefont.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto1.htm b/api/vendor/setasign/fpdf/tutorial/tuto1.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto1.php b/api/vendor/setasign/fpdf/tutorial/tuto1.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto2.htm b/api/vendor/setasign/fpdf/tutorial/tuto2.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto2.php b/api/vendor/setasign/fpdf/tutorial/tuto2.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto3.htm b/api/vendor/setasign/fpdf/tutorial/tuto3.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto3.php b/api/vendor/setasign/fpdf/tutorial/tuto3.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto4.htm b/api/vendor/setasign/fpdf/tutorial/tuto4.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto4.php b/api/vendor/setasign/fpdf/tutorial/tuto4.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto5.htm b/api/vendor/setasign/fpdf/tutorial/tuto5.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto5.php b/api/vendor/setasign/fpdf/tutorial/tuto5.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto6.htm b/api/vendor/setasign/fpdf/tutorial/tuto6.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto6.php b/api/vendor/setasign/fpdf/tutorial/tuto6.php old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto7.htm b/api/vendor/setasign/fpdf/tutorial/tuto7.htm old mode 100644 new mode 100755 diff --git a/api/vendor/setasign/fpdf/tutorial/tuto7.php b/api/vendor/setasign/fpdf/tutorial/tuto7.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/.gitignore b/api/vendor/stripe/stripe-php/.gitignore old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/API_VERSION b/api/vendor/stripe/stripe-php/API_VERSION old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/CHANGELOG.md b/api/vendor/stripe/stripe-php/CHANGELOG.md old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/CONTRIBUTING.md b/api/vendor/stripe/stripe-php/CONTRIBUTING.md old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/LICENSE b/api/vendor/stripe/stripe-php/LICENSE old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/OPENAPI_VERSION b/api/vendor/stripe/stripe-php/OPENAPI_VERSION old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/README.md b/api/vendor/stripe/stripe-php/README.md old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/VERSION b/api/vendor/stripe/stripe-php/VERSION old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/composer.json b/api/vendor/stripe/stripe-php/composer.json old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/data/ca-certificates.crt b/api/vendor/stripe/stripe-php/data/ca-certificates.crt old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/init.php b/api/vendor/stripe/stripe-php/init.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/justfile b/api/vendor/stripe/stripe-php/justfile old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Account.php b/api/vendor/stripe/stripe-php/lib/Account.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/AccountLink.php b/api/vendor/stripe/stripe-php/lib/AccountLink.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/AccountSession.php b/api/vendor/stripe/stripe-php/lib/AccountSession.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiOperations/All.php b/api/vendor/stripe/stripe-php/lib/ApiOperations/All.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiOperations/Create.php b/api/vendor/stripe/stripe-php/lib/ApiOperations/Create.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiOperations/Delete.php b/api/vendor/stripe/stripe-php/lib/ApiOperations/Delete.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiOperations/NestedResource.php b/api/vendor/stripe/stripe-php/lib/ApiOperations/NestedResource.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiOperations/Request.php b/api/vendor/stripe/stripe-php/lib/ApiOperations/Request.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiOperations/Retrieve.php b/api/vendor/stripe/stripe-php/lib/ApiOperations/Retrieve.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiOperations/SingletonRetrieve.php b/api/vendor/stripe/stripe-php/lib/ApiOperations/SingletonRetrieve.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiOperations/Update.php b/api/vendor/stripe/stripe-php/lib/ApiOperations/Update.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiRequestor.php b/api/vendor/stripe/stripe-php/lib/ApiRequestor.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiResource.php b/api/vendor/stripe/stripe-php/lib/ApiResource.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApiResponse.php b/api/vendor/stripe/stripe-php/lib/ApiResponse.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApplePayDomain.php b/api/vendor/stripe/stripe-php/lib/ApplePayDomain.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Application.php b/api/vendor/stripe/stripe-php/lib/Application.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApplicationFee.php b/api/vendor/stripe/stripe-php/lib/ApplicationFee.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ApplicationFeeRefund.php b/api/vendor/stripe/stripe-php/lib/ApplicationFeeRefund.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Apps/Secret.php b/api/vendor/stripe/stripe-php/lib/Apps/Secret.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Balance.php b/api/vendor/stripe/stripe-php/lib/Balance.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/BalanceTransaction.php b/api/vendor/stripe/stripe-php/lib/BalanceTransaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/BankAccount.php b/api/vendor/stripe/stripe-php/lib/BankAccount.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/BaseStripeClient.php b/api/vendor/stripe/stripe-php/lib/BaseStripeClient.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/BaseStripeClientInterface.php b/api/vendor/stripe/stripe-php/lib/BaseStripeClientInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Billing/Alert.php b/api/vendor/stripe/stripe-php/lib/Billing/Alert.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Billing/AlertTriggered.php b/api/vendor/stripe/stripe-php/lib/Billing/AlertTriggered.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Billing/CreditBalanceSummary.php b/api/vendor/stripe/stripe-php/lib/Billing/CreditBalanceSummary.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Billing/CreditBalanceTransaction.php b/api/vendor/stripe/stripe-php/lib/Billing/CreditBalanceTransaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Billing/CreditGrant.php b/api/vendor/stripe/stripe-php/lib/Billing/CreditGrant.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Billing/Meter.php b/api/vendor/stripe/stripe-php/lib/Billing/Meter.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Billing/MeterEvent.php b/api/vendor/stripe/stripe-php/lib/Billing/MeterEvent.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Billing/MeterEventAdjustment.php b/api/vendor/stripe/stripe-php/lib/Billing/MeterEventAdjustment.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Billing/MeterEventSummary.php b/api/vendor/stripe/stripe-php/lib/Billing/MeterEventSummary.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/BillingPortal/Configuration.php b/api/vendor/stripe/stripe-php/lib/BillingPortal/Configuration.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/BillingPortal/Session.php b/api/vendor/stripe/stripe-php/lib/BillingPortal/Session.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Capability.php b/api/vendor/stripe/stripe-php/lib/Capability.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Card.php b/api/vendor/stripe/stripe-php/lib/Card.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/CashBalance.php b/api/vendor/stripe/stripe-php/lib/CashBalance.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Charge.php b/api/vendor/stripe/stripe-php/lib/Charge.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Checkout/Session.php b/api/vendor/stripe/stripe-php/lib/Checkout/Session.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Climate/Order.php b/api/vendor/stripe/stripe-php/lib/Climate/Order.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Climate/Product.php b/api/vendor/stripe/stripe-php/lib/Climate/Product.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Climate/Supplier.php b/api/vendor/stripe/stripe-php/lib/Climate/Supplier.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Collection.php b/api/vendor/stripe/stripe-php/lib/Collection.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ConfirmationToken.php b/api/vendor/stripe/stripe-php/lib/ConfirmationToken.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ConnectCollectionTransfer.php b/api/vendor/stripe/stripe-php/lib/ConnectCollectionTransfer.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/CountrySpec.php b/api/vendor/stripe/stripe-php/lib/CountrySpec.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Coupon.php b/api/vendor/stripe/stripe-php/lib/Coupon.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/CreditNote.php b/api/vendor/stripe/stripe-php/lib/CreditNote.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/CreditNoteLineItem.php b/api/vendor/stripe/stripe-php/lib/CreditNoteLineItem.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Customer.php b/api/vendor/stripe/stripe-php/lib/Customer.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/CustomerBalanceTransaction.php b/api/vendor/stripe/stripe-php/lib/CustomerBalanceTransaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/CustomerCashBalanceTransaction.php b/api/vendor/stripe/stripe-php/lib/CustomerCashBalanceTransaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/CustomerSession.php b/api/vendor/stripe/stripe-php/lib/CustomerSession.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Discount.php b/api/vendor/stripe/stripe-php/lib/Discount.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Dispute.php b/api/vendor/stripe/stripe-php/lib/Dispute.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Entitlements/ActiveEntitlement.php b/api/vendor/stripe/stripe-php/lib/Entitlements/ActiveEntitlement.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Entitlements/ActiveEntitlementSummary.php b/api/vendor/stripe/stripe-php/lib/Entitlements/ActiveEntitlementSummary.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Entitlements/Feature.php b/api/vendor/stripe/stripe-php/lib/Entitlements/Feature.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/EphemeralKey.php b/api/vendor/stripe/stripe-php/lib/EphemeralKey.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ErrorObject.php b/api/vendor/stripe/stripe-php/lib/ErrorObject.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Event.php b/api/vendor/stripe/stripe-php/lib/Event.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/EventData/V1BillingMeterErrorReportTriggeredEventData.php b/api/vendor/stripe/stripe-php/lib/EventData/V1BillingMeterErrorReportTriggeredEventData.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/EventData/V1BillingMeterNoMeterFoundEventData.php b/api/vendor/stripe/stripe-php/lib/EventData/V1BillingMeterNoMeterFoundEventData.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Events/V1BillingMeterErrorReportTriggeredEvent.php b/api/vendor/stripe/stripe-php/lib/Events/V1BillingMeterErrorReportTriggeredEvent.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Events/V1BillingMeterNoMeterFoundEvent.php b/api/vendor/stripe/stripe-php/lib/Events/V1BillingMeterNoMeterFoundEvent.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Events/V2CoreEventDestinationPingEvent.php b/api/vendor/stripe/stripe-php/lib/Events/V2CoreEventDestinationPingEvent.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/ApiConnectionException.php b/api/vendor/stripe/stripe-php/lib/Exception/ApiConnectionException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/ApiErrorException.php b/api/vendor/stripe/stripe-php/lib/Exception/ApiErrorException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/AuthenticationException.php b/api/vendor/stripe/stripe-php/lib/Exception/AuthenticationException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/BadMethodCallException.php b/api/vendor/stripe/stripe-php/lib/Exception/BadMethodCallException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/CardException.php b/api/vendor/stripe/stripe-php/lib/Exception/CardException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/ExceptionInterface.php b/api/vendor/stripe/stripe-php/lib/Exception/ExceptionInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/IdempotencyException.php b/api/vendor/stripe/stripe-php/lib/Exception/IdempotencyException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/InvalidArgumentException.php b/api/vendor/stripe/stripe-php/lib/Exception/InvalidArgumentException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/InvalidRequestException.php b/api/vendor/stripe/stripe-php/lib/Exception/InvalidRequestException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/OAuth/ExceptionInterface.php b/api/vendor/stripe/stripe-php/lib/Exception/OAuth/ExceptionInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/OAuth/InvalidClientException.php b/api/vendor/stripe/stripe-php/lib/Exception/OAuth/InvalidClientException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/OAuth/InvalidGrantException.php b/api/vendor/stripe/stripe-php/lib/Exception/OAuth/InvalidGrantException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/OAuth/InvalidRequestException.php b/api/vendor/stripe/stripe-php/lib/Exception/OAuth/InvalidRequestException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/OAuth/InvalidScopeException.php b/api/vendor/stripe/stripe-php/lib/Exception/OAuth/InvalidScopeException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/OAuth/OAuthErrorException.php b/api/vendor/stripe/stripe-php/lib/Exception/OAuth/OAuthErrorException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/OAuth/UnknownOAuthErrorException.php b/api/vendor/stripe/stripe-php/lib/Exception/OAuth/UnknownOAuthErrorException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/OAuth/UnsupportedGrantTypeException.php b/api/vendor/stripe/stripe-php/lib/Exception/OAuth/UnsupportedGrantTypeException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/OAuth/UnsupportedResponseTypeException.php b/api/vendor/stripe/stripe-php/lib/Exception/OAuth/UnsupportedResponseTypeException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/PermissionException.php b/api/vendor/stripe/stripe-php/lib/Exception/PermissionException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/RateLimitException.php b/api/vendor/stripe/stripe-php/lib/Exception/RateLimitException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/SignatureVerificationException.php b/api/vendor/stripe/stripe-php/lib/Exception/SignatureVerificationException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/TemporarySessionExpiredException.php b/api/vendor/stripe/stripe-php/lib/Exception/TemporarySessionExpiredException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/UnexpectedValueException.php b/api/vendor/stripe/stripe-php/lib/Exception/UnexpectedValueException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Exception/UnknownApiErrorException.php b/api/vendor/stripe/stripe-php/lib/Exception/UnknownApiErrorException.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ExchangeRate.php b/api/vendor/stripe/stripe-php/lib/ExchangeRate.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/File.php b/api/vendor/stripe/stripe-php/lib/File.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/FileLink.php b/api/vendor/stripe/stripe-php/lib/FileLink.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/FinancialConnections/Account.php b/api/vendor/stripe/stripe-php/lib/FinancialConnections/Account.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/FinancialConnections/AccountOwner.php b/api/vendor/stripe/stripe-php/lib/FinancialConnections/AccountOwner.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/FinancialConnections/AccountOwnership.php b/api/vendor/stripe/stripe-php/lib/FinancialConnections/AccountOwnership.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/FinancialConnections/Session.php b/api/vendor/stripe/stripe-php/lib/FinancialConnections/Session.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/FinancialConnections/Transaction.php b/api/vendor/stripe/stripe-php/lib/FinancialConnections/Transaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Forwarding/Request.php b/api/vendor/stripe/stripe-php/lib/Forwarding/Request.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/FundingInstructions.php b/api/vendor/stripe/stripe-php/lib/FundingInstructions.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/HttpClient/ClientInterface.php b/api/vendor/stripe/stripe-php/lib/HttpClient/ClientInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/HttpClient/CurlClient.php b/api/vendor/stripe/stripe-php/lib/HttpClient/CurlClient.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/HttpClient/StreamingClientInterface.php b/api/vendor/stripe/stripe-php/lib/HttpClient/StreamingClientInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Identity/VerificationReport.php b/api/vendor/stripe/stripe-php/lib/Identity/VerificationReport.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Identity/VerificationSession.php b/api/vendor/stripe/stripe-php/lib/Identity/VerificationSession.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Invoice.php b/api/vendor/stripe/stripe-php/lib/Invoice.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/InvoiceItem.php b/api/vendor/stripe/stripe-php/lib/InvoiceItem.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/InvoiceLineItem.php b/api/vendor/stripe/stripe-php/lib/InvoiceLineItem.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/InvoicePayment.php b/api/vendor/stripe/stripe-php/lib/InvoicePayment.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/InvoiceRenderingTemplate.php b/api/vendor/stripe/stripe-php/lib/InvoiceRenderingTemplate.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Issuing/Authorization.php b/api/vendor/stripe/stripe-php/lib/Issuing/Authorization.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Issuing/Card.php b/api/vendor/stripe/stripe-php/lib/Issuing/Card.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Issuing/CardDetails.php b/api/vendor/stripe/stripe-php/lib/Issuing/CardDetails.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Issuing/Cardholder.php b/api/vendor/stripe/stripe-php/lib/Issuing/Cardholder.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Issuing/Dispute.php b/api/vendor/stripe/stripe-php/lib/Issuing/Dispute.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Issuing/PersonalizationDesign.php b/api/vendor/stripe/stripe-php/lib/Issuing/PersonalizationDesign.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Issuing/PhysicalBundle.php b/api/vendor/stripe/stripe-php/lib/Issuing/PhysicalBundle.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Issuing/Token.php b/api/vendor/stripe/stripe-php/lib/Issuing/Token.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Issuing/Transaction.php b/api/vendor/stripe/stripe-php/lib/Issuing/Transaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/LineItem.php b/api/vendor/stripe/stripe-php/lib/LineItem.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/LoginLink.php b/api/vendor/stripe/stripe-php/lib/LoginLink.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Mandate.php b/api/vendor/stripe/stripe-php/lib/Mandate.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/OAuth.php b/api/vendor/stripe/stripe-php/lib/OAuth.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/OAuthErrorObject.php b/api/vendor/stripe/stripe-php/lib/OAuthErrorObject.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/PaymentIntent.php b/api/vendor/stripe/stripe-php/lib/PaymentIntent.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/PaymentLink.php b/api/vendor/stripe/stripe-php/lib/PaymentLink.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/PaymentMethod.php b/api/vendor/stripe/stripe-php/lib/PaymentMethod.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/PaymentMethodConfiguration.php b/api/vendor/stripe/stripe-php/lib/PaymentMethodConfiguration.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/PaymentMethodDomain.php b/api/vendor/stripe/stripe-php/lib/PaymentMethodDomain.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Payout.php b/api/vendor/stripe/stripe-php/lib/Payout.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Person.php b/api/vendor/stripe/stripe-php/lib/Person.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Plan.php b/api/vendor/stripe/stripe-php/lib/Plan.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Price.php b/api/vendor/stripe/stripe-php/lib/Price.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Product.php b/api/vendor/stripe/stripe-php/lib/Product.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ProductFeature.php b/api/vendor/stripe/stripe-php/lib/ProductFeature.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/PromotionCode.php b/api/vendor/stripe/stripe-php/lib/PromotionCode.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Quote.php b/api/vendor/stripe/stripe-php/lib/Quote.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Radar/EarlyFraudWarning.php b/api/vendor/stripe/stripe-php/lib/Radar/EarlyFraudWarning.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Radar/ValueList.php b/api/vendor/stripe/stripe-php/lib/Radar/ValueList.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Radar/ValueListItem.php b/api/vendor/stripe/stripe-php/lib/Radar/ValueListItem.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Reason.php b/api/vendor/stripe/stripe-php/lib/Reason.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/RecipientTransfer.php b/api/vendor/stripe/stripe-php/lib/RecipientTransfer.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Refund.php b/api/vendor/stripe/stripe-php/lib/Refund.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/RelatedObject.php b/api/vendor/stripe/stripe-php/lib/RelatedObject.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Reporting/ReportRun.php b/api/vendor/stripe/stripe-php/lib/Reporting/ReportRun.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Reporting/ReportType.php b/api/vendor/stripe/stripe-php/lib/Reporting/ReportType.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/RequestTelemetry.php b/api/vendor/stripe/stripe-php/lib/RequestTelemetry.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ReserveTransaction.php b/api/vendor/stripe/stripe-php/lib/ReserveTransaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Review.php b/api/vendor/stripe/stripe-php/lib/Review.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/SearchResult.php b/api/vendor/stripe/stripe-php/lib/SearchResult.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/AbstractService.php b/api/vendor/stripe/stripe-php/lib/Service/AbstractService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/AbstractServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/AbstractServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/AccountLinkService.php b/api/vendor/stripe/stripe-php/lib/Service/AccountLinkService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/AccountService.php b/api/vendor/stripe/stripe-php/lib/Service/AccountService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/AccountSessionService.php b/api/vendor/stripe/stripe-php/lib/Service/AccountSessionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/ApplePayDomainService.php b/api/vendor/stripe/stripe-php/lib/Service/ApplePayDomainService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/ApplicationFeeService.php b/api/vendor/stripe/stripe-php/lib/Service/ApplicationFeeService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Apps/AppsServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Apps/AppsServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Apps/SecretService.php b/api/vendor/stripe/stripe-php/lib/Service/Apps/SecretService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/BalanceService.php b/api/vendor/stripe/stripe-php/lib/Service/BalanceService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/BalanceTransactionService.php b/api/vendor/stripe/stripe-php/lib/Service/BalanceTransactionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Billing/AlertService.php b/api/vendor/stripe/stripe-php/lib/Service/Billing/AlertService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Billing/BillingServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Billing/BillingServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Billing/CreditBalanceSummaryService.php b/api/vendor/stripe/stripe-php/lib/Service/Billing/CreditBalanceSummaryService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Billing/CreditBalanceTransactionService.php b/api/vendor/stripe/stripe-php/lib/Service/Billing/CreditBalanceTransactionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Billing/CreditGrantService.php b/api/vendor/stripe/stripe-php/lib/Service/Billing/CreditGrantService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Billing/MeterEventAdjustmentService.php b/api/vendor/stripe/stripe-php/lib/Service/Billing/MeterEventAdjustmentService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Billing/MeterEventService.php b/api/vendor/stripe/stripe-php/lib/Service/Billing/MeterEventService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Billing/MeterService.php b/api/vendor/stripe/stripe-php/lib/Service/Billing/MeterService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/BillingPortal/BillingPortalServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/BillingPortal/BillingPortalServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/BillingPortal/ConfigurationService.php b/api/vendor/stripe/stripe-php/lib/Service/BillingPortal/ConfigurationService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/BillingPortal/SessionService.php b/api/vendor/stripe/stripe-php/lib/Service/BillingPortal/SessionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/ChargeService.php b/api/vendor/stripe/stripe-php/lib/Service/ChargeService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Checkout/CheckoutServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Checkout/CheckoutServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Checkout/SessionService.php b/api/vendor/stripe/stripe-php/lib/Service/Checkout/SessionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Climate/ClimateServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Climate/ClimateServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Climate/OrderService.php b/api/vendor/stripe/stripe-php/lib/Service/Climate/OrderService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Climate/ProductService.php b/api/vendor/stripe/stripe-php/lib/Service/Climate/ProductService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Climate/SupplierService.php b/api/vendor/stripe/stripe-php/lib/Service/Climate/SupplierService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/ConfirmationTokenService.php b/api/vendor/stripe/stripe-php/lib/Service/ConfirmationTokenService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/CoreServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/CoreServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/CountrySpecService.php b/api/vendor/stripe/stripe-php/lib/Service/CountrySpecService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/CouponService.php b/api/vendor/stripe/stripe-php/lib/Service/CouponService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/CreditNoteService.php b/api/vendor/stripe/stripe-php/lib/Service/CreditNoteService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/CustomerService.php b/api/vendor/stripe/stripe-php/lib/Service/CustomerService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/CustomerSessionService.php b/api/vendor/stripe/stripe-php/lib/Service/CustomerSessionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/DisputeService.php b/api/vendor/stripe/stripe-php/lib/Service/DisputeService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Entitlements/ActiveEntitlementService.php b/api/vendor/stripe/stripe-php/lib/Service/Entitlements/ActiveEntitlementService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Entitlements/EntitlementsServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Entitlements/EntitlementsServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Entitlements/FeatureService.php b/api/vendor/stripe/stripe-php/lib/Service/Entitlements/FeatureService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/EphemeralKeyService.php b/api/vendor/stripe/stripe-php/lib/Service/EphemeralKeyService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/EventService.php b/api/vendor/stripe/stripe-php/lib/Service/EventService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/ExchangeRateService.php b/api/vendor/stripe/stripe-php/lib/Service/ExchangeRateService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/FileLinkService.php b/api/vendor/stripe/stripe-php/lib/Service/FileLinkService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/FileService.php b/api/vendor/stripe/stripe-php/lib/Service/FileService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/FinancialConnections/AccountService.php b/api/vendor/stripe/stripe-php/lib/Service/FinancialConnections/AccountService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/FinancialConnections/FinancialConnectionsServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/FinancialConnections/FinancialConnectionsServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/FinancialConnections/SessionService.php b/api/vendor/stripe/stripe-php/lib/Service/FinancialConnections/SessionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/FinancialConnections/TransactionService.php b/api/vendor/stripe/stripe-php/lib/Service/FinancialConnections/TransactionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Forwarding/ForwardingServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Forwarding/ForwardingServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Forwarding/RequestService.php b/api/vendor/stripe/stripe-php/lib/Service/Forwarding/RequestService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Identity/IdentityServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Identity/IdentityServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Identity/VerificationReportService.php b/api/vendor/stripe/stripe-php/lib/Service/Identity/VerificationReportService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Identity/VerificationSessionService.php b/api/vendor/stripe/stripe-php/lib/Service/Identity/VerificationSessionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/InvoiceItemService.php b/api/vendor/stripe/stripe-php/lib/Service/InvoiceItemService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/InvoicePaymentService.php b/api/vendor/stripe/stripe-php/lib/Service/InvoicePaymentService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/InvoiceRenderingTemplateService.php b/api/vendor/stripe/stripe-php/lib/Service/InvoiceRenderingTemplateService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/InvoiceService.php b/api/vendor/stripe/stripe-php/lib/Service/InvoiceService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Issuing/AuthorizationService.php b/api/vendor/stripe/stripe-php/lib/Service/Issuing/AuthorizationService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Issuing/CardService.php b/api/vendor/stripe/stripe-php/lib/Service/Issuing/CardService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Issuing/CardholderService.php b/api/vendor/stripe/stripe-php/lib/Service/Issuing/CardholderService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Issuing/DisputeService.php b/api/vendor/stripe/stripe-php/lib/Service/Issuing/DisputeService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Issuing/IssuingServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Issuing/IssuingServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Issuing/PersonalizationDesignService.php b/api/vendor/stripe/stripe-php/lib/Service/Issuing/PersonalizationDesignService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Issuing/PhysicalBundleService.php b/api/vendor/stripe/stripe-php/lib/Service/Issuing/PhysicalBundleService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Issuing/TokenService.php b/api/vendor/stripe/stripe-php/lib/Service/Issuing/TokenService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Issuing/TransactionService.php b/api/vendor/stripe/stripe-php/lib/Service/Issuing/TransactionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/MandateService.php b/api/vendor/stripe/stripe-php/lib/Service/MandateService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/OAuthService.php b/api/vendor/stripe/stripe-php/lib/Service/OAuthService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/PaymentIntentService.php b/api/vendor/stripe/stripe-php/lib/Service/PaymentIntentService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/PaymentLinkService.php b/api/vendor/stripe/stripe-php/lib/Service/PaymentLinkService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/PaymentMethodConfigurationService.php b/api/vendor/stripe/stripe-php/lib/Service/PaymentMethodConfigurationService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/PaymentMethodDomainService.php b/api/vendor/stripe/stripe-php/lib/Service/PaymentMethodDomainService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/PaymentMethodService.php b/api/vendor/stripe/stripe-php/lib/Service/PaymentMethodService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/PayoutService.php b/api/vendor/stripe/stripe-php/lib/Service/PayoutService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/PlanService.php b/api/vendor/stripe/stripe-php/lib/Service/PlanService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/PriceService.php b/api/vendor/stripe/stripe-php/lib/Service/PriceService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/ProductService.php b/api/vendor/stripe/stripe-php/lib/Service/ProductService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/PromotionCodeService.php b/api/vendor/stripe/stripe-php/lib/Service/PromotionCodeService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/QuoteService.php b/api/vendor/stripe/stripe-php/lib/Service/QuoteService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Radar/EarlyFraudWarningService.php b/api/vendor/stripe/stripe-php/lib/Service/Radar/EarlyFraudWarningService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Radar/RadarServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Radar/RadarServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Radar/ValueListItemService.php b/api/vendor/stripe/stripe-php/lib/Service/Radar/ValueListItemService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Radar/ValueListService.php b/api/vendor/stripe/stripe-php/lib/Service/Radar/ValueListService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/RefundService.php b/api/vendor/stripe/stripe-php/lib/Service/RefundService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Reporting/ReportRunService.php b/api/vendor/stripe/stripe-php/lib/Service/Reporting/ReportRunService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Reporting/ReportTypeService.php b/api/vendor/stripe/stripe-php/lib/Service/Reporting/ReportTypeService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Reporting/ReportingServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Reporting/ReportingServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/ReviewService.php b/api/vendor/stripe/stripe-php/lib/Service/ReviewService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/ServiceNavigatorTrait.php b/api/vendor/stripe/stripe-php/lib/Service/ServiceNavigatorTrait.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/SetupAttemptService.php b/api/vendor/stripe/stripe-php/lib/Service/SetupAttemptService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/SetupIntentService.php b/api/vendor/stripe/stripe-php/lib/Service/SetupIntentService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/ShippingRateService.php b/api/vendor/stripe/stripe-php/lib/Service/ShippingRateService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Sigma/ScheduledQueryRunService.php b/api/vendor/stripe/stripe-php/lib/Service/Sigma/ScheduledQueryRunService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Sigma/SigmaServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Sigma/SigmaServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/SourceService.php b/api/vendor/stripe/stripe-php/lib/Service/SourceService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/SubscriptionItemService.php b/api/vendor/stripe/stripe-php/lib/Service/SubscriptionItemService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/SubscriptionScheduleService.php b/api/vendor/stripe/stripe-php/lib/Service/SubscriptionScheduleService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/SubscriptionService.php b/api/vendor/stripe/stripe-php/lib/Service/SubscriptionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Tax/CalculationService.php b/api/vendor/stripe/stripe-php/lib/Service/Tax/CalculationService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Tax/RegistrationService.php b/api/vendor/stripe/stripe-php/lib/Service/Tax/RegistrationService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Tax/SettingsService.php b/api/vendor/stripe/stripe-php/lib/Service/Tax/SettingsService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Tax/TaxServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Tax/TaxServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Tax/TransactionService.php b/api/vendor/stripe/stripe-php/lib/Service/Tax/TransactionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TaxCodeService.php b/api/vendor/stripe/stripe-php/lib/Service/TaxCodeService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TaxIdService.php b/api/vendor/stripe/stripe-php/lib/Service/TaxIdService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TaxRateService.php b/api/vendor/stripe/stripe-php/lib/Service/TaxRateService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Terminal/ConfigurationService.php b/api/vendor/stripe/stripe-php/lib/Service/Terminal/ConfigurationService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Terminal/ConnectionTokenService.php b/api/vendor/stripe/stripe-php/lib/Service/Terminal/ConnectionTokenService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Terminal/LocationService.php b/api/vendor/stripe/stripe-php/lib/Service/Terminal/LocationService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Terminal/ReaderService.php b/api/vendor/stripe/stripe-php/lib/Service/Terminal/ReaderService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Terminal/TerminalServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Terminal/TerminalServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/ConfirmationTokenService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/ConfirmationTokenService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/CustomerService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/CustomerService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/AuthorizationService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/AuthorizationService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/CardService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/CardService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/IssuingServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/IssuingServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/PersonalizationDesignService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/PersonalizationDesignService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/TransactionService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Issuing/TransactionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/RefundService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/RefundService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Terminal/ReaderService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Terminal/ReaderService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Terminal/TerminalServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Terminal/TerminalServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/TestClockService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/TestClockService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/TestHelpersServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/TestHelpersServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/InboundTransferService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/InboundTransferService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/OutboundPaymentService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/OutboundPaymentService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/OutboundTransferService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/OutboundTransferService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/ReceivedCreditService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/ReceivedCreditService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/ReceivedDebitService.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/ReceivedDebitService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/TreasuryServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/TestHelpers/Treasury/TreasuryServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TokenService.php b/api/vendor/stripe/stripe-php/lib/Service/TokenService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TopupService.php b/api/vendor/stripe/stripe-php/lib/Service/TopupService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/TransferService.php b/api/vendor/stripe/stripe-php/lib/Service/TransferService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/CreditReversalService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/CreditReversalService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/DebitReversalService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/DebitReversalService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/FinancialAccountService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/FinancialAccountService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/InboundTransferService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/InboundTransferService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/OutboundPaymentService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/OutboundPaymentService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/OutboundTransferService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/OutboundTransferService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/ReceivedCreditService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/ReceivedCreditService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/ReceivedDebitService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/ReceivedDebitService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/TransactionEntryService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/TransactionEntryService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/TransactionService.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/TransactionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/Treasury/TreasuryServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/Treasury/TreasuryServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/BillingServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/BillingServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/MeterEventAdjustmentService.php b/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/MeterEventAdjustmentService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/MeterEventService.php b/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/MeterEventService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/MeterEventSessionService.php b/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/MeterEventSessionService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/MeterEventStreamService.php b/api/vendor/stripe/stripe-php/lib/Service/V2/Billing/MeterEventStreamService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/V2/Core/CoreServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/V2/Core/CoreServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/V2/Core/EventDestinationService.php b/api/vendor/stripe/stripe-php/lib/Service/V2/Core/EventDestinationService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/V2/Core/EventService.php b/api/vendor/stripe/stripe-php/lib/Service/V2/Core/EventService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/V2/V2ServiceFactory.php b/api/vendor/stripe/stripe-php/lib/Service/V2/V2ServiceFactory.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Service/WebhookEndpointService.php b/api/vendor/stripe/stripe-php/lib/Service/WebhookEndpointService.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/SetupAttempt.php b/api/vendor/stripe/stripe-php/lib/SetupAttempt.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/SetupIntent.php b/api/vendor/stripe/stripe-php/lib/SetupIntent.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ShippingRate.php b/api/vendor/stripe/stripe-php/lib/ShippingRate.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Sigma/ScheduledQueryRun.php b/api/vendor/stripe/stripe-php/lib/Sigma/ScheduledQueryRun.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/SingletonApiResource.php b/api/vendor/stripe/stripe-php/lib/SingletonApiResource.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Source.php b/api/vendor/stripe/stripe-php/lib/Source.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/SourceMandateNotification.php b/api/vendor/stripe/stripe-php/lib/SourceMandateNotification.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/SourceTransaction.php b/api/vendor/stripe/stripe-php/lib/SourceTransaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Stripe.php b/api/vendor/stripe/stripe-php/lib/Stripe.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/StripeClient.php b/api/vendor/stripe/stripe-php/lib/StripeClient.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/StripeClientInterface.php b/api/vendor/stripe/stripe-php/lib/StripeClientInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/StripeObject.php b/api/vendor/stripe/stripe-php/lib/StripeObject.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/StripeStreamingClientInterface.php b/api/vendor/stripe/stripe-php/lib/StripeStreamingClientInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Subscription.php b/api/vendor/stripe/stripe-php/lib/Subscription.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/SubscriptionItem.php b/api/vendor/stripe/stripe-php/lib/SubscriptionItem.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/SubscriptionSchedule.php b/api/vendor/stripe/stripe-php/lib/SubscriptionSchedule.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Tax/Calculation.php b/api/vendor/stripe/stripe-php/lib/Tax/Calculation.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Tax/CalculationLineItem.php b/api/vendor/stripe/stripe-php/lib/Tax/CalculationLineItem.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Tax/Registration.php b/api/vendor/stripe/stripe-php/lib/Tax/Registration.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Tax/Settings.php b/api/vendor/stripe/stripe-php/lib/Tax/Settings.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Tax/Transaction.php b/api/vendor/stripe/stripe-php/lib/Tax/Transaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Tax/TransactionLineItem.php b/api/vendor/stripe/stripe-php/lib/Tax/TransactionLineItem.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/TaxCode.php b/api/vendor/stripe/stripe-php/lib/TaxCode.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/TaxDeductedAtSource.php b/api/vendor/stripe/stripe-php/lib/TaxDeductedAtSource.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/TaxId.php b/api/vendor/stripe/stripe-php/lib/TaxId.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/TaxRate.php b/api/vendor/stripe/stripe-php/lib/TaxRate.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Terminal/Configuration.php b/api/vendor/stripe/stripe-php/lib/Terminal/Configuration.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Terminal/ConnectionToken.php b/api/vendor/stripe/stripe-php/lib/Terminal/ConnectionToken.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Terminal/Location.php b/api/vendor/stripe/stripe-php/lib/Terminal/Location.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Terminal/Reader.php b/api/vendor/stripe/stripe-php/lib/Terminal/Reader.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/TestHelpers/TestClock.php b/api/vendor/stripe/stripe-php/lib/TestHelpers/TestClock.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/ThinEvent.php b/api/vendor/stripe/stripe-php/lib/ThinEvent.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Token.php b/api/vendor/stripe/stripe-php/lib/Token.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Topup.php b/api/vendor/stripe/stripe-php/lib/Topup.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Transfer.php b/api/vendor/stripe/stripe-php/lib/Transfer.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/TransferReversal.php b/api/vendor/stripe/stripe-php/lib/TransferReversal.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/CreditReversal.php b/api/vendor/stripe/stripe-php/lib/Treasury/CreditReversal.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/DebitReversal.php b/api/vendor/stripe/stripe-php/lib/Treasury/DebitReversal.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/FinancialAccount.php b/api/vendor/stripe/stripe-php/lib/Treasury/FinancialAccount.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/FinancialAccountFeatures.php b/api/vendor/stripe/stripe-php/lib/Treasury/FinancialAccountFeatures.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/InboundTransfer.php b/api/vendor/stripe/stripe-php/lib/Treasury/InboundTransfer.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/OutboundPayment.php b/api/vendor/stripe/stripe-php/lib/Treasury/OutboundPayment.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/OutboundTransfer.php b/api/vendor/stripe/stripe-php/lib/Treasury/OutboundTransfer.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/ReceivedCredit.php b/api/vendor/stripe/stripe-php/lib/Treasury/ReceivedCredit.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/ReceivedDebit.php b/api/vendor/stripe/stripe-php/lib/Treasury/ReceivedDebit.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/Transaction.php b/api/vendor/stripe/stripe-php/lib/Treasury/Transaction.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Treasury/TransactionEntry.php b/api/vendor/stripe/stripe-php/lib/Treasury/TransactionEntry.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/ApiVersion.php b/api/vendor/stripe/stripe-php/lib/Util/ApiVersion.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/CaseInsensitiveArray.php b/api/vendor/stripe/stripe-php/lib/Util/CaseInsensitiveArray.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/DefaultLogger.php b/api/vendor/stripe/stripe-php/lib/Util/DefaultLogger.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/EventTypes.php b/api/vendor/stripe/stripe-php/lib/Util/EventTypes.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/LoggerInterface.php b/api/vendor/stripe/stripe-php/lib/Util/LoggerInterface.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/ObjectTypes.php b/api/vendor/stripe/stripe-php/lib/Util/ObjectTypes.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/RandomGenerator.php b/api/vendor/stripe/stripe-php/lib/Util/RandomGenerator.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/RequestOptions.php b/api/vendor/stripe/stripe-php/lib/Util/RequestOptions.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/Set.php b/api/vendor/stripe/stripe-php/lib/Util/Set.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Util/Util.php b/api/vendor/stripe/stripe-php/lib/Util/Util.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/V2/Billing/MeterEvent.php b/api/vendor/stripe/stripe-php/lib/V2/Billing/MeterEvent.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/V2/Billing/MeterEventAdjustment.php b/api/vendor/stripe/stripe-php/lib/V2/Billing/MeterEventAdjustment.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/V2/Billing/MeterEventSession.php b/api/vendor/stripe/stripe-php/lib/V2/Billing/MeterEventSession.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/V2/Collection.php b/api/vendor/stripe/stripe-php/lib/V2/Collection.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/V2/Event.php b/api/vendor/stripe/stripe-php/lib/V2/Event.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/V2/EventDestination.php b/api/vendor/stripe/stripe-php/lib/V2/EventDestination.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/Webhook.php b/api/vendor/stripe/stripe-php/lib/Webhook.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/WebhookEndpoint.php b/api/vendor/stripe/stripe-php/lib/WebhookEndpoint.php old mode 100644 new mode 100755 diff --git a/api/vendor/stripe/stripe-php/lib/WebhookSignature.php b/api/vendor/stripe/stripe-php/lib/WebhookSignature.php old mode 100644 new mode 100755 diff --git a/app/.bundle/config b/app/.bundle/config old mode 100644 new mode 100755 diff --git a/app/.dart_tool/dartpad/web_plugin_registrant.dart b/app/.dart_tool/dartpad/web_plugin_registrant.dart old mode 100644 new mode 100755 diff --git a/app/.dart_tool/package_config.json b/app/.dart_tool/package_config.json old mode 100644 new mode 100755 index 08c8aa77..1c4d4cee --- a/app/.dart_tool/package_config.json +++ b/app/.dart_tool/package_config.json @@ -3,1165 +3,1165 @@ "packages": [ { "name": "_fe_analyzer_shared", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-72.0.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/_fe_analyzer_shared-72.0.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "_macros", - "rootUri": "file:///home/pierre/.local/flutter/bin/cache/dart-sdk/pkg/_macros", + "rootUri": "file:///opt/flutter/bin/cache/dart-sdk/pkg/_macros", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "analyzer", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/analyzer-6.7.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/analyzer-6.7.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "archive", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/archive-4.0.7", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/archive-4.0.7", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "args", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/args-2.7.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/args-2.7.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "async", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/async-2.11.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/async-2.11.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "battery_plus", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/battery_plus-6.0.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/battery_plus-6.0.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "battery_plus_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/battery_plus_platform_interface-2.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/battery_plus_platform_interface-2.0.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "boolean_selector", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/boolean_selector-2.1.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "build", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/build-2.4.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/build-2.4.1", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "build_config", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/build_config-1.1.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/build_config-1.1.1", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "build_daemon", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/build_daemon-4.0.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/build_daemon-4.0.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "build_resolvers", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/build_resolvers-2.4.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/build_resolvers-2.4.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "build_runner", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/build_runner-2.4.13", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/build_runner-2.4.13", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "build_runner_core", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/build_runner_core-7.3.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/build_runner_core-7.3.2", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "built_collection", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/built_collection-5.1.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/built_collection-5.1.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "built_value", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/built_value-8.12.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/built_value-8.12.3", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "characters", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/characters-1.3.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/characters-1.3.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "charcode", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/charcode-1.4.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/charcode-1.4.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "checked_yaml", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/checked_yaml-2.0.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/checked_yaml-2.0.3", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "class_to_string", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/class_to_string-1.1.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/class_to_string-1.1.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "cli_util", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/cli_util-0.4.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/cli_util-0.4.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "clock", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/clock-1.1.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/clock-1.1.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "code_builder", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/code_builder-4.10.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/code_builder-4.10.1", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "collection", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/collection-1.18.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/collection-1.18.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "connectivity_plus", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/connectivity_plus-6.0.5", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "connectivity_plus_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus_platform_interface-2.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/connectivity_plus_platform_interface-2.0.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "convert", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/convert-3.1.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/convert-3.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "cookie_jar", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/cookie_jar-4.0.8", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/cookie_jar-4.0.8", "packageUri": "lib/", "languageVersion": "2.15" }, { "name": "cross_file", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/cross_file-0.3.4+2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/cross_file-0.3.4+2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "crypto", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/crypto-3.0.7", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/crypto-3.0.7", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "csslib", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/csslib-1.0.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/csslib-1.0.2", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "cupertino_icons", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/cupertino_icons-1.0.8", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "dart_earcut", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/dart_earcut-1.2.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/dart_earcut-1.2.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "dart_style", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/dart_style-2.3.7", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/dart_style-2.3.7", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "dbus", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/dbus-0.7.11", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/dbus-0.7.11", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "device_info_plus", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/device_info_plus-11.3.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "device_info_plus_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/device_info_plus_platform_interface-7.0.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/device_info_plus_platform_interface-7.0.2", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/dio-5.9.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/dio-5.9.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio_cache_interceptor", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/dio_cache_interceptor-3.5.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/dio_cache_interceptor-3.5.1", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "dio_cache_interceptor_hive_store", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/dio_cache_interceptor_hive_store-3.2.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/dio_cache_interceptor_hive_store-3.2.2", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "dio_cookie_manager", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/dio_cookie_manager-3.3.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/dio_cookie_manager-3.3.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio_web_adapter", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/dio_web_adapter-2.1.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/dio_web_adapter-2.1.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "fake_async", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/fake_async-1.3.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/fake_async-1.3.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "ffi", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/ffi-2.1.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/ffi-2.1.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "file", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/file-7.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/file-7.0.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "file_selector_linux", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/file_selector_linux-0.9.3+2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/file_selector_linux-0.9.3+2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "file_selector_macos", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/file_selector_macos-0.9.4+2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/file_selector_macos-0.9.4+2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "file_selector_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/file_selector_platform_interface-2.6.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/file_selector_platform_interface-2.6.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "file_selector_windows", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/file_selector_windows-0.9.3+4", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/file_selector_windows-0.9.3+4", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "fixnum", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/fixnum-1.1.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/fixnum-1.1.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "flutter", - "rootUri": "file:///home/pierre/.local/flutter/packages/flutter", + "rootUri": "file:///opt/flutter/packages/flutter", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "flutter_compass", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_compass-0.8.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_compass-0.8.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "flutter_launcher_icons", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_launcher_icons-0.14.4", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_launcher_icons-0.14.4", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "flutter_lints", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_lints-5.0.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_lints-5.0.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "flutter_local_notifications", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications-19.5.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_local_notifications-19.5.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "flutter_local_notifications_linux", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_linux-6.0.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_local_notifications_linux-6.0.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "flutter_local_notifications_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_platform_interface-9.1.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_local_notifications_platform_interface-9.1.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "flutter_local_notifications_windows", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_windows-1.0.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_local_notifications_windows-1.0.3", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "flutter_localizations", - "rootUri": "file:///home/pierre/.local/flutter/packages/flutter_localizations", + "rootUri": "file:///opt/flutter/packages/flutter_localizations", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "flutter_map", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_map-7.0.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_map-7.0.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "flutter_map_cache", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_map_cache-1.5.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_map_cache-1.5.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "flutter_plugin_android_lifecycle", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.26", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.26", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "flutter_stripe", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_stripe-11.5.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_stripe-11.5.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "flutter_svg", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/flutter_svg-2.1.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_svg-2.1.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "flutter_test", - "rootUri": "file:///home/pierre/.local/flutter/packages/flutter_test", + "rootUri": "file:///opt/flutter/packages/flutter_test", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "flutter_web_plugins", - "rootUri": "file:///home/pierre/.local/flutter/packages/flutter_web_plugins", + "rootUri": "file:///opt/flutter/packages/flutter_web_plugins", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "freezed_annotation", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/freezed_annotation-2.4.4", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/freezed_annotation-2.4.4", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "frontend_server_client", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/frontend_server_client-4.0.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/frontend_server_client-4.0.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "geolocator", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/geolocator-13.0.4", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator-13.0.4", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "geolocator_android", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/geolocator_android-4.6.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_android-4.6.1", "packageUri": "lib/", "languageVersion": "2.15" }, { "name": "geolocator_apple", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.13", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_apple-2.3.13", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "geolocator_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/geolocator_platform_interface-4.2.6", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_platform_interface-4.2.6", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "geolocator_web", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/geolocator_web-4.1.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_web-4.1.3", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "geolocator_windows", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/geolocator_windows-0.2.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_windows-0.2.5", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "glob", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/glob-2.1.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/glob-2.1.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "go_router", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/go_router-15.1.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/go_router-15.1.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "google_fonts", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/google_fonts-6.3.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/google_fonts-6.3.0", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "graphs", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/graphs-2.3.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/graphs-2.3.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "hive", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/hive-2.2.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/hive-2.2.3", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "hive_flutter", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/hive_flutter-1.1.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/hive_flutter-1.1.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "hive_generator", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/hive_generator-2.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/hive_generator-2.0.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "html", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/html-0.15.6", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/html-0.15.6", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "http", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/http-1.6.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/http-1.6.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "http_multi_server", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/http_multi_server-3.2.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/http_multi_server-3.2.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "http_parser", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/http_parser-4.0.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/http_parser-4.0.2", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "image", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/image-4.7.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image-4.7.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "image_picker", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/image_picker-0.8.9", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker-0.8.9", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "image_picker_android", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/image_picker_android-0.8.12+21", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_android-0.8.12+21", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "image_picker_for_web", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/image_picker_for_web-2.1.12", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_for_web-2.1.12", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "image_picker_ios", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/image_picker_ios-0.8.12+2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_ios-0.8.12+2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "image_picker_linux", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/image_picker_linux-0.2.1+2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_linux-0.2.1+2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "image_picker_macos", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/image_picker_macos-0.2.1+2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_macos-0.2.1+2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "image_picker_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/image_picker_platform_interface-2.10.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_platform_interface-2.10.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "image_picker_windows", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/image_picker_windows-0.2.1+1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_windows-0.2.1+1", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "intl", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/intl-0.19.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/intl-0.19.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "io", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/io-1.0.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/io-1.0.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "js", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/js-0.7.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/js-0.7.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "json_annotation", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/json_annotation-4.9.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/json_annotation-4.9.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "latlong2", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/latlong2-0.9.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/latlong2-0.9.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "leak_tracker", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/leak_tracker-10.0.5", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_flutter_testing", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_testing", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/leak_tracker_testing-3.0.1", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "lints", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/lints-5.0.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/lints-5.0.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "lists", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/lists-1.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/lists-1.0.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "logger", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/logger-2.6.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/logger-2.6.2", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "logging", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/logging-1.3.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/logging-1.3.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "macros", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/macros-0.1.2-main.4", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/macros-0.1.2-main.4", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "matcher", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/matcher-0.12.16+1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/matcher-0.12.16+1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "material_color_utilities", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/material_color_utilities-0.11.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "mek_data_class", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/mek_data_class-1.4.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/mek_data_class-1.4.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "mek_stripe_terminal", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/mek_stripe_terminal-4.6.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/mek_stripe_terminal-4.6.1", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "meta", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/meta-1.15.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/meta-1.15.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "mgrs_dart", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/mgrs_dart-2.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "mime", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/mime-2.0.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/mime-2.0.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "nfc_manager", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/nfc_manager-3.3.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "nm", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/nm-0.5.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/nm-0.5.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "one_for_all", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/one_for_all-1.1.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/one_for_all-1.1.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "package_config", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/package_config-2.2.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/package_config-2.2.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/path-1.9.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path-1.9.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "path_parsing", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/path_parsing-1.1.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_parsing-1.1.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "path_provider", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/path_provider-2.1.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider-2.1.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "path_provider_android", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/path_provider_android-2.2.15", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_android-2.2.15", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "path_provider_foundation", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_foundation-2.4.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "path_provider_linux", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_linux-2.2.1", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "path_provider_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_platform_interface-2.1.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "path_provider_windows", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_windows-2.3.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "permission_handler", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/permission_handler-12.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler-12.0.1", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "permission_handler_android", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/permission_handler_android-13.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler_android-13.0.1", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "permission_handler_apple", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/permission_handler_apple-9.4.7", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler_apple-9.4.7", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "permission_handler_html", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/permission_handler_html-0.1.3+5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler_html-0.1.3+5", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "permission_handler_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/permission_handler_platform_interface-4.3.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler_platform_interface-4.3.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "permission_handler_windows", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/permission_handler_windows-0.2.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler_windows-0.2.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "petitparser", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/petitparser-6.0.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/petitparser-6.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "platform", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/platform-3.1.6", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/platform-3.1.6", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "plugin_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/plugin_platform_interface-2.1.8", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "polylabel", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/polylabel-1.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/polylabel-1.0.1", "packageUri": "lib/", "languageVersion": "2.13" }, { "name": "pool", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/pool-1.5.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/pool-1.5.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "posix", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/posix-6.0.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/posix-6.0.3", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "proj4dart", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/proj4dart-2.1.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/proj4dart-2.1.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "pub_semver", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/pub_semver-2.2.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/pub_semver-2.2.0", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "pubspec_parse", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/pubspec_parse-1.4.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/pubspec_parse-1.4.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "qr", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/qr-3.0.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/qr-3.0.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "qr_flutter", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/qr_flutter-4.1.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/qr_flutter-4.1.0", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "recase", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/recase-4.1.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/recase-4.1.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "retry", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/retry-3.1.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/retry-3.1.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "shelf", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/shelf-1.4.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/shelf-1.4.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "shelf_web_socket", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/shelf_web_socket-2.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/shelf_web_socket-2.0.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "sky_engine", - "rootUri": "file:///home/pierre/.local/flutter/bin/cache/pkg/sky_engine", + "rootUri": "file:///opt/flutter/bin/cache/pkg/sky_engine", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "source_gen", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/source_gen-1.5.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/source_gen-1.5.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "source_helper", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/source_helper-1.3.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/source_helper-1.3.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "source_span", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/source_span-1.10.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/source_span-1.10.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "stack_trace", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/stack_trace-1.11.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/stack_trace-1.11.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "stream_channel", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/stream_channel-2.1.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/stream_channel-2.1.2", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "stream_transform", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/stream_transform-2.1.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/stream_transform-2.1.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "string_scanner", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/string_scanner-1.2.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/string_scanner-1.2.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "stripe_android", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/stripe_android-11.5.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/stripe_android-11.5.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "stripe_ios", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/stripe_ios-11.5.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/stripe_ios-11.5.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "stripe_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/stripe_platform_interface-11.5.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/stripe_platform_interface-11.5.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "syncfusion_flutter_charts", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/syncfusion_flutter_charts-27.2.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/syncfusion_flutter_charts-27.2.5", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "syncfusion_flutter_core", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-27.2.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/syncfusion_flutter_core-27.2.5", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "term_glyph", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/term_glyph-1.2.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "test_api", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/test_api-0.7.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/test_api-0.7.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "timezone", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/timezone-0.10.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/timezone-0.10.1", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "timing", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/timing-1.0.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/timing-1.0.2", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "typed_data", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/typed_data-1.4.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/typed_data-1.4.0", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "unicode", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/unicode-0.3.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/unicode-0.3.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "universal_html", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/universal_html-2.2.4", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/universal_html-2.2.4", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "universal_io", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/universal_io-2.2.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/universal_io-2.2.2", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "upower", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/upower-0.7.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/upower-0.7.0", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "url_launcher", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/url_launcher-6.3.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher-6.3.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "url_launcher_android", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.14", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_android-6.3.14", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "url_launcher_ios", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_ios-6.3.3", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "url_launcher_linux", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_linux-3.2.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "url_launcher_macos", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_macos-3.2.2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "url_launcher_platform_interface", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/url_launcher_platform_interface-2.3.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_platform_interface-2.3.2", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "url_launcher_web", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/url_launcher_web-2.3.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_web-2.3.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "url_launcher_windows", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_windows-3.1.4", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "uuid", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/uuid-4.5.2", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/uuid-4.5.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "vector_graphics", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/vector_graphics-1.1.18", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/vector_graphics-1.1.18", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "vector_graphics_codec", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.13", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/vector_graphics_codec-1.1.13", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "vector_graphics_compiler", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.16", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/vector_graphics_compiler-1.1.16", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "vector_math", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/vector_math-2.1.4", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/vector_math-2.1.4", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "vm_service", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/vm_service-14.2.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/vm_service-14.2.5", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "watcher", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/watcher-1.2.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/watcher-1.2.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "web", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/web-1.1.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/web-1.1.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "web_socket", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/web_socket-1.0.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/web_socket-1.0.1", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "web_socket_channel", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/web_socket_channel-3.0.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/web_socket_channel-3.0.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "win32", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/win32-5.10.1", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/win32-5.10.1", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "win32_registry", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/win32_registry-1.1.5", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/win32_registry-1.1.5", "packageUri": "lib/", "languageVersion": "3.4" }, { "name": "wkt_parser", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/wkt_parser-2.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "xdg_directories", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/xdg_directories-1.1.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "xml", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/xml-6.5.0", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/xml-6.5.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "yaml", - "rootUri": "file:///home/pierre/.pub-cache/hosted/pub.dev/yaml-3.1.3", + "rootUri": "file:///home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/yaml-3.1.3", "packageUri": "lib/", "languageVersion": "3.4" }, @@ -1172,10 +1172,10 @@ "languageVersion": "3.0" } ], - "generated": "2026-01-19T15:01:26.574661Z", + "generated": "2026-01-26T15:48:33.358665Z", "generator": "pub", "generatorVersion": "3.5.4", - "flutterRoot": "file:///home/pierre/.local/flutter", + "flutterRoot": "file:///opt/flutter", "flutterVersion": "3.24.5", - "pubCache": "file:///home/pierre/.pub-cache" + "pubCache": "file:///home/pierre/dev/geosector/app/.pub-cache-local" } diff --git a/app/.dart_tool/version b/app/.dart_tool/version old mode 100644 new mode 100755 diff --git a/app/.flutter-plugins-dependencies b/app/.flutter-plugins-dependencies old mode 100644 new mode 100755 index 620794af..79c70d7d --- a/app/.flutter-plugins-dependencies +++ b/app/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"battery_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/battery_plus-6.0.3/","native_build":true,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":true,"dependencies":[]},{"name":"flutter_compass","path":"/home/pierre/.pub-cache/hosted/pub.dev/flutter_compass-0.8.1/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications","path":"/home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications-19.5.0/","native_build":true,"dependencies":[]},{"name":"geolocator_apple","path":"/home/pierre/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.13/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_ios","path":"/home/pierre/.pub-cache/hosted/pub.dev/image_picker_ios-0.8.12+2/","native_build":true,"dependencies":[]},{"name":"mek_stripe_terminal","path":"/home/pierre/.pub-cache/hosted/pub.dev/mek_stripe_terminal-4.6.1/","native_build":true,"dependencies":[]},{"name":"nfc_manager","path":"/home/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/pierre/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.1/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"permission_handler_apple","path":"/home/pierre/.pub-cache/hosted/pub.dev/permission_handler_apple-9.4.7/","native_build":true,"dependencies":[]},{"name":"stripe_ios","path":"/home/pierre/.pub-cache/hosted/pub.dev/stripe_ios-11.5.0/","native_build":true,"dependencies":[]},{"name":"url_launcher_ios","path":"/home/pierre/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.3/","native_build":true,"dependencies":[]}],"android":[{"name":"battery_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/battery_plus-6.0.3/","native_build":true,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":true,"dependencies":[]},{"name":"flutter_compass","path":"/home/pierre/.pub-cache/hosted/pub.dev/flutter_compass-0.8.1/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications","path":"/home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications-19.5.0/","native_build":true,"dependencies":[]},{"name":"flutter_plugin_android_lifecycle","path":"/home/pierre/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.26/","native_build":true,"dependencies":[]},{"name":"geolocator_android","path":"/home/pierre/.pub-cache/hosted/pub.dev/geolocator_android-4.6.1/","native_build":true,"dependencies":[]},{"name":"image_picker_android","path":"/home/pierre/.pub-cache/hosted/pub.dev/image_picker_android-0.8.12+21/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"mek_stripe_terminal","path":"/home/pierre/.pub-cache/hosted/pub.dev/mek_stripe_terminal-4.6.1/","native_build":true,"dependencies":[]},{"name":"nfc_manager","path":"/home/pierre/.pub-cache/hosted/pub.dev/nfc_manager-3.3.0/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/home/pierre/.pub-cache/hosted/pub.dev/path_provider_android-2.2.15/","native_build":true,"dependencies":[]},{"name":"permission_handler_android","path":"/home/pierre/.pub-cache/hosted/pub.dev/permission_handler_android-13.0.1/","native_build":true,"dependencies":[]},{"name":"stripe_android","path":"/home/pierre/.pub-cache/hosted/pub.dev/stripe_android-11.5.0/","native_build":true,"dependencies":[]},{"name":"url_launcher_android","path":"/home/pierre/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.14/","native_build":true,"dependencies":[]}],"macos":[{"name":"battery_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/battery_plus-6.0.3/","native_build":true,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":true,"dependencies":[]},{"name":"file_selector_macos","path":"/home/pierre/.pub-cache/hosted/pub.dev/file_selector_macos-0.9.4+2/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications","path":"/home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications-19.5.0/","native_build":true,"dependencies":[]},{"name":"geolocator_apple","path":"/home/pierre/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.13/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_macos","path":"/home/pierre/.pub-cache/hosted/pub.dev/image_picker_macos-0.2.1+2/","native_build":false,"dependencies":["file_selector_macos"]},{"name":"path_provider_foundation","path":"/home/pierre/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.1/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"url_launcher_macos","path":"/home/pierre/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.2/","native_build":true,"dependencies":[]}],"linux":[{"name":"battery_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/battery_plus-6.0.3/","native_build":false,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","native_build":false,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":false,"dependencies":[]},{"name":"file_selector_linux","path":"/home/pierre/.pub-cache/hosted/pub.dev/file_selector_linux-0.9.3+2/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications_linux","path":"/home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_linux-6.0.0/","native_build":false,"dependencies":[]},{"name":"image_picker_linux","path":"/home/pierre/.pub-cache/hosted/pub.dev/image_picker_linux-0.2.1+2/","native_build":false,"dependencies":["file_selector_linux"]},{"name":"path_provider_linux","path":"/home/pierre/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]},{"name":"url_launcher_linux","path":"/home/pierre/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/","native_build":true,"dependencies":[]}],"windows":[{"name":"battery_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/battery_plus-6.0.3/","native_build":true,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","native_build":false,"dependencies":[]},{"name":"file_selector_windows","path":"/home/pierre/.pub-cache/hosted/pub.dev/file_selector_windows-0.9.3+4/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications_windows","path":"/home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_windows-1.0.3/","native_build":true,"dependencies":[]},{"name":"geolocator_windows","path":"/home/pierre/.pub-cache/hosted/pub.dev/geolocator_windows-0.2.5/","native_build":true,"dependencies":[]},{"name":"image_picker_windows","path":"/home/pierre/.pub-cache/hosted/pub.dev/image_picker_windows-0.2.1+1/","native_build":false,"dependencies":["file_selector_windows"]},{"name":"path_provider_windows","path":"/home/pierre/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[]},{"name":"permission_handler_windows","path":"/home/pierre/.pub-cache/hosted/pub.dev/permission_handler_windows-0.2.1/","native_build":true,"dependencies":[]},{"name":"url_launcher_windows","path":"/home/pierre/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4/","native_build":true,"dependencies":[]}],"web":[{"name":"battery_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/battery_plus-6.0.3/","dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/","dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/","dependencies":[]},{"name":"geolocator_web","path":"/home/pierre/.pub-cache/hosted/pub.dev/geolocator_web-4.1.3/","dependencies":[]},{"name":"image_picker_for_web","path":"/home/pierre/.pub-cache/hosted/pub.dev/image_picker_for_web-2.1.12/","dependencies":[]},{"name":"permission_handler_html","path":"/home/pierre/.pub-cache/hosted/pub.dev/permission_handler_html-0.1.3+5/","dependencies":[]},{"name":"url_launcher_web","path":"/home/pierre/.pub-cache/hosted/pub.dev/url_launcher_web-2.3.3/","dependencies":[]}]},"dependencyGraph":[{"name":"battery_plus","dependencies":[]},{"name":"connectivity_plus","dependencies":[]},{"name":"device_info_plus","dependencies":[]},{"name":"file_selector_linux","dependencies":[]},{"name":"file_selector_macos","dependencies":[]},{"name":"file_selector_windows","dependencies":[]},{"name":"flutter_compass","dependencies":[]},{"name":"flutter_local_notifications","dependencies":["flutter_local_notifications_linux","flutter_local_notifications_windows"]},{"name":"flutter_local_notifications_linux","dependencies":[]},{"name":"flutter_local_notifications_windows","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"flutter_stripe","dependencies":["stripe_android","stripe_ios"]},{"name":"geolocator","dependencies":["geolocator_android","geolocator_apple","geolocator_web","geolocator_windows"]},{"name":"geolocator_android","dependencies":[]},{"name":"geolocator_apple","dependencies":[]},{"name":"geolocator_web","dependencies":[]},{"name":"geolocator_windows","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios","image_picker_linux","image_picker_macos","image_picker_windows"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"image_picker_linux","dependencies":["file_selector_linux"]},{"name":"image_picker_macos","dependencies":["file_selector_macos"]},{"name":"image_picker_windows","dependencies":["file_selector_windows"]},{"name":"mek_stripe_terminal","dependencies":[]},{"name":"nfc_manager","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_html","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_html","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]},{"name":"stripe_android","dependencies":[]},{"name":"stripe_ios","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2026-01-19 16:03:59.511412","version":"3.24.5","swift_package_manager_enabled":false} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"battery_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/battery_plus-6.0.3/","native_build":true,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/connectivity_plus-6.0.5/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/device_info_plus-11.3.0/","native_build":true,"dependencies":[]},{"name":"flutter_compass","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_compass-0.8.1/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_local_notifications-19.5.0/","native_build":true,"dependencies":[]},{"name":"geolocator_apple","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_apple-2.3.13/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_ios","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_ios-0.8.12+2/","native_build":true,"dependencies":[]},{"name":"mek_stripe_terminal","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/mek_stripe_terminal-4.6.1/","native_build":true,"dependencies":[]},{"name":"nfc_manager","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/nfc_manager-3.3.0/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_foundation-2.4.1/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"permission_handler_apple","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler_apple-9.4.7/","native_build":true,"dependencies":[]},{"name":"stripe_ios","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/stripe_ios-11.5.0/","native_build":true,"dependencies":[]},{"name":"url_launcher_ios","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_ios-6.3.3/","native_build":true,"dependencies":[]}],"android":[{"name":"battery_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/battery_plus-6.0.3/","native_build":true,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/connectivity_plus-6.0.5/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/device_info_plus-11.3.0/","native_build":true,"dependencies":[]},{"name":"flutter_compass","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_compass-0.8.1/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_local_notifications-19.5.0/","native_build":true,"dependencies":[]},{"name":"flutter_plugin_android_lifecycle","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.26/","native_build":true,"dependencies":[]},{"name":"geolocator_android","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_android-4.6.1/","native_build":true,"dependencies":[]},{"name":"image_picker_android","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_android-0.8.12+21/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"mek_stripe_terminal","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/mek_stripe_terminal-4.6.1/","native_build":true,"dependencies":[]},{"name":"nfc_manager","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/nfc_manager-3.3.0/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_android-2.2.15/","native_build":true,"dependencies":[]},{"name":"permission_handler_android","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler_android-13.0.1/","native_build":true,"dependencies":[]},{"name":"stripe_android","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/stripe_android-11.5.0/","native_build":true,"dependencies":[]},{"name":"url_launcher_android","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_android-6.3.14/","native_build":true,"dependencies":[]}],"macos":[{"name":"battery_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/battery_plus-6.0.3/","native_build":true,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/connectivity_plus-6.0.5/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/device_info_plus-11.3.0/","native_build":true,"dependencies":[]},{"name":"file_selector_macos","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/file_selector_macos-0.9.4+2/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_local_notifications-19.5.0/","native_build":true,"dependencies":[]},{"name":"geolocator_apple","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_apple-2.3.13/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"image_picker_macos","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_macos-0.2.1+2/","native_build":false,"dependencies":["file_selector_macos"]},{"name":"path_provider_foundation","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_foundation-2.4.1/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"url_launcher_macos","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_macos-3.2.2/","native_build":true,"dependencies":[]}],"linux":[{"name":"battery_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/battery_plus-6.0.3/","native_build":false,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/connectivity_plus-6.0.5/","native_build":false,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/device_info_plus-11.3.0/","native_build":false,"dependencies":[]},{"name":"file_selector_linux","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/file_selector_linux-0.9.3+2/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications_linux","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_local_notifications_linux-6.0.0/","native_build":false,"dependencies":[]},{"name":"image_picker_linux","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_linux-0.2.1+2/","native_build":false,"dependencies":["file_selector_linux"]},{"name":"path_provider_linux","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]},{"name":"url_launcher_linux","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_linux-3.2.1/","native_build":true,"dependencies":[]}],"windows":[{"name":"battery_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/battery_plus-6.0.3/","native_build":true,"dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/connectivity_plus-6.0.5/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/device_info_plus-11.3.0/","native_build":false,"dependencies":[]},{"name":"file_selector_windows","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/file_selector_windows-0.9.3+4/","native_build":true,"dependencies":[]},{"name":"flutter_local_notifications_windows","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/flutter_local_notifications_windows-1.0.3/","native_build":true,"dependencies":[]},{"name":"geolocator_windows","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_windows-0.2.5/","native_build":true,"dependencies":[]},{"name":"image_picker_windows","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_windows-0.2.1+1/","native_build":false,"dependencies":["file_selector_windows"]},{"name":"path_provider_windows","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[]},{"name":"permission_handler_windows","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler_windows-0.2.1/","native_build":true,"dependencies":[]},{"name":"url_launcher_windows","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_windows-3.1.4/","native_build":true,"dependencies":[]}],"web":[{"name":"battery_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/battery_plus-6.0.3/","dependencies":[]},{"name":"connectivity_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/connectivity_plus-6.0.5/","dependencies":[]},{"name":"device_info_plus","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/device_info_plus-11.3.0/","dependencies":[]},{"name":"geolocator_web","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/geolocator_web-4.1.3/","dependencies":[]},{"name":"image_picker_for_web","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/image_picker_for_web-2.1.12/","dependencies":[]},{"name":"permission_handler_html","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/permission_handler_html-0.1.3+5/","dependencies":[]},{"name":"url_launcher_web","path":"/home/pierre/dev/geosector/app/.pub-cache-local/hosted/pub.dev/url_launcher_web-2.3.3/","dependencies":[]}]},"dependencyGraph":[{"name":"battery_plus","dependencies":[]},{"name":"connectivity_plus","dependencies":[]},{"name":"device_info_plus","dependencies":[]},{"name":"file_selector_linux","dependencies":[]},{"name":"file_selector_macos","dependencies":[]},{"name":"file_selector_windows","dependencies":[]},{"name":"flutter_compass","dependencies":[]},{"name":"flutter_local_notifications","dependencies":["flutter_local_notifications_linux","flutter_local_notifications_windows"]},{"name":"flutter_local_notifications_linux","dependencies":[]},{"name":"flutter_local_notifications_windows","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"flutter_stripe","dependencies":["stripe_android","stripe_ios"]},{"name":"geolocator","dependencies":["geolocator_android","geolocator_apple","geolocator_web","geolocator_windows"]},{"name":"geolocator_android","dependencies":[]},{"name":"geolocator_apple","dependencies":[]},{"name":"geolocator_web","dependencies":[]},{"name":"geolocator_windows","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios","image_picker_linux","image_picker_macos","image_picker_windows"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"image_picker_linux","dependencies":["file_selector_linux"]},{"name":"image_picker_macos","dependencies":["file_selector_macos"]},{"name":"image_picker_windows","dependencies":["file_selector_windows"]},{"name":"mek_stripe_terminal","dependencies":[]},{"name":"nfc_manager","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":["permission_handler_android","permission_handler_apple","permission_handler_html","permission_handler_windows"]},{"name":"permission_handler_android","dependencies":[]},{"name":"permission_handler_apple","dependencies":[]},{"name":"permission_handler_html","dependencies":[]},{"name":"permission_handler_windows","dependencies":[]},{"name":"stripe_android","dependencies":[]},{"name":"stripe_ios","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2026-01-26 16:48:42.797283","version":"3.24.5","swift_package_manager_enabled":false} \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore old mode 100644 new mode 100755 diff --git a/app/.metadata b/app/.metadata old mode 100644 new mode 100755 diff --git a/app/ANDROID-GUIDE.md b/app/ANDROID-GUIDE.md old mode 100644 new mode 100755 diff --git a/app/BUILD-IOS-SUCCESS.md b/app/BUILD-IOS-SUCCESS.md old mode 100644 new mode 100755 diff --git a/app/BUNDLE-ID-UPDATE.md b/app/BUNDLE-ID-UPDATE.md old mode 100644 new mode 100755 diff --git a/app/FASTLANE.md b/app/FASTLANE.md old mode 100644 new mode 100755 diff --git a/app/Gemfile b/app/Gemfile old mode 100644 new mode 100755 diff --git a/app/Gemfile.lock b/app/Gemfile.lock old mode 100644 new mode 100755 diff --git a/app/IOS-BUILD-GUIDE.md b/app/IOS-BUILD-GUIDE.md old mode 100644 new mode 100755 diff --git a/app/MIGRATION_FLUTTER_3.24.5.md b/app/MIGRATION_FLUTTER_3.24.5.md old mode 100644 new mode 100755 diff --git a/app/QUICK-START.md b/app/QUICK-START.md old mode 100644 new mode 100755 diff --git a/app/README-IOS.md b/app/README-IOS.md old mode 100644 new mode 100755 diff --git a/app/README-SCRIPTS.md b/app/README-SCRIPTS.md old mode 100644 new mode 100755 diff --git a/app/README.md b/app/README.md old mode 100644 new mode 100755 diff --git a/app/SCRIPTS-IOS.md b/app/SCRIPTS-IOS.md old mode 100644 new mode 100755 diff --git a/app/SOLUTION-IOS.md b/app/SOLUTION-IOS.md old mode 100644 new mode 100755 diff --git a/app/TRANSFERT-MAC.md b/app/TRANSFERT-MAC.md old mode 100644 new mode 100755 diff --git a/app/android.sh b/app/android.sh index 55fa4f88..cfc6c0ae 100755 --- a/app/android.sh +++ b/app/android.sh @@ -39,25 +39,19 @@ handle_error() { # Trap pour capturer les erreurs trap 'handle_error $LINENO' ERR -# Vérifier que nous sommes dans le bon dossier -if [ ! -f "pubspec.yaml" ]; then - print_error "Ce script doit être exécuté depuis le dossier racine de l'application Flutter" - print_error "Fichier pubspec.yaml introuvable" - exit 1 -fi +# Variables pour IN1 (compilation distante) +IN1_HOST="IN1" +IN1_PROJECT_PATH="/home/pierre/dev/geosector/app" + +print_message "🖥️ Compilation distante sur IN1:${IN1_PROJECT_PATH}" +echo print_message "=========================================" print_message " GEOSECTOR - Génération Bundle Android" print_message "=========================================" echo -# Vérifier que Flutter est installé -if ! command -v flutter &> /dev/null; then - print_error "Flutter n'est pas installé ou n'est pas dans le PATH" - exit 1 -fi - -# Étape 0 : Synchroniser la version depuis ../VERSION +# Étape 0 : Synchroniser la version depuis ../VERSION (lecture locale via SSHFS) print_message "Étape 0/5 : Synchronisation de la version..." echo @@ -230,88 +224,89 @@ if [ "$USE_R8" = true ]; then echo fi -# Étape 1 : Nettoyer le projet -print_message "Étape 1/5 : Nettoyage du projet..." -flutter clean -if [ $? -eq 0 ]; then - print_success "Projet nettoyé" -else - print_error "Échec du nettoyage du projet" - exit 1 -fi -echo - -# Étape 2 : Récupérer les dépendances -print_message "Étape 2/5 : Récupération des dépendances..." -flutter pub get -if [ $? -eq 0 ]; then - print_success "Dépendances récupérées" -else - print_error "Échec de la récupération des dépendances" - exit 1 -fi -echo - -# Étape 2.5 : Patcher nfc_manager pour AGP 8+ -print_message "Étape 2.5/5 : Patch nfc_manager pour Android Gradle Plugin 8+..." -NFC_PATCH_SCRIPT="./fastlane/scripts/commun/fix-nfc-manager.sh" -if [ -f "$NFC_PATCH_SCRIPT" ]; then - bash "$NFC_PATCH_SCRIPT" - if [ $? -eq 0 ]; then - print_success "Patch nfc_manager appliqué" - else - print_warning "Le patch nfc_manager a échoué (peut être déjà appliqué)" - fi -else - print_warning "Script de patch nfc_manager introuvable : $NFC_PATCH_SCRIPT" -fi -echo - -# Étape 3 : Analyser le code (optionnel mais recommandé) -print_message "Étape 3/5 : Analyse du code Dart..." -flutter analyze --no-fatal-infos --no-fatal-warnings || { - print_warning "Des avertissements ont été détectés dans le code" - read -p "Voulez-vous continuer malgré les avertissements ? (y/n) " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - print_message "Génération annulée par l'utilisateur" - exit 0 - fi -} -print_success "Analyse du code terminée" -echo - -# Étape 4 : Générer le bundle -print_message "Étape 4/5 : Génération du bundle Android..." +# Lancer le build sur IN1 via SSH +print_message "🚀 Lancement du build Android sur IN1..." print_message "Cette opération peut prendre plusieurs minutes..." -flutter build appbundle $BUILD_MODE_FLAG -if [ $? -eq 0 ]; then - print_success "Bundle généré avec succès" -else - print_error "Échec de la génération du bundle" - exit 1 -fi echo -# Restaurer le build.gradle.kts original si modifié -if [ "$USE_R8" = true ] && [ -f "$GRADLE_BACKUP" ]; then - print_message "Restauration du build.gradle.kts original..." - mv "$GRADLE_BACKUP" "$GRADLE_FILE" - print_success "Fichier restauré" - echo +ssh ${IN1_HOST} "bash -l -s" </dev/null && { + print_success "Fichier mapping.txt téléchargé" + } || { + print_warning "Fichier mapping.txt introuvable sur IN1 (peut être normal)" + } - # Copier les symboles natifs - SYMBOLS_ZIP="build/app/intermediates/merged_native_libs/release/out/lib" - if [ -d "$SYMBOLS_ZIP" ]; then - # Créer une archive des symboles - cd build/app/intermediates/merged_native_libs/release/out - zip -r "../../../../../../$RELEASE_DIR/native-symbols.zip" lib/ - cd - > /dev/null - print_success "Symboles natifs archivés" - else + # Créer l'archive des symboles natifs sur IN1 et la télécharger + print_message "Creating and downloading native symbols..." + ssh ${IN1_HOST} "bash -l -c ' + cd ${IN1_PROJECT_PATH}/build/app/intermediates/merged_native_libs/release/out 2>/dev/null && + zip -r /tmp/native-symbols-$VERSION_CODE.zip lib/ && + echo \"Symbols archived\" + '" 2>/dev/null && { + scp ${IN1_HOST}:/tmp/native-symbols-$VERSION_CODE.zip "$RELEASE_DIR/native-symbols.zip" && { + print_success "Symboles natifs téléchargés" + ssh ${IN1_HOST} "rm -f /tmp/native-symbols-$VERSION_CODE.zip" + } + } || { print_warning "Symboles natifs introuvables (peut être normal)" - fi + } - print_success "Fichiers de débogage copiés dans : $RELEASE_DIR/" + print_success "Fichiers de débogage dans : $RELEASE_DIR/" echo print_message "Pour uploader sur Google Play Console :" print_message "1. Bundle : $RELEASE_DIR/$FINAL_NAME" @@ -410,48 +408,80 @@ echo read -p "Voulez-vous aussi générer l'APK pour des tests ? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then - print_message "Génération de l'APK..." - flutter build apk $BUILD_MODE_FLAG + print_message "Génération de l'APK sur IN1..." + + ssh ${IN1_HOST} "bash -l -s" </dev/null || print_warning "Aucune version précédente trouvée" - print_message "Installation sur l'appareil..." - adb install "$APK_NAME" + # Vérifier qu'ADB est disponible localement + if ! command -v adb &> /dev/null; then + print_error "ADB n'est pas installé sur ce poste" + print_message "Installez Android SDK Platform Tools" + else + # Vérifier qu'un appareil est connecté + print_message "Vérification des appareils connectés..." + DEVICES=$(adb devices | grep -v "List" | grep "device$" | wc -l) - if [ $? -eq 0 ]; then - print_success "APK installé avec succès" + if [ "$DEVICES" -eq 0 ]; then + print_error "Aucun appareil Android détecté en USB sur ce poste" + print_message "Vérifiez la connexion USB et activez le débogage USB" + print_message "Commande : adb devices" + else + print_success "$DEVICES appareil(s) détecté(s)" + print_message "Désinstallation de l'ancienne version..." + adb uninstall fr.geosector.app3 2>/dev/null || print_warning "Aucune version précédente trouvée" + + print_message "Installation sur l'appareil..." + adb install "$APK_NAME" - # Proposer de lancer l'app - read -p "Lancer l'application ? (y/n) " -n 1 -r - echo - if [[ $REPLY =~ ^[Yy]$ ]]; then - adb shell am start -n fr.geosector.app3/.MainActivity if [ $? -eq 0 ]; then - print_success "Application lancée" + print_success "APK installé avec succès sur l'appareil connecté" + + # Proposer de lancer l'app + read -p "Lancer l'application ? (y/n) " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + adb shell am start -n fr.geosector.app3/.MainActivity + if [ $? -eq 0 ]; then + print_success "Application lancée" + else + print_warning "Impossible de lancer l'application" + fi + fi else - print_warning "Impossible de lancer l'application" + print_error "Échec de l'installation" + print_message "Commande : adb install $APK_NAME" fi fi - else - print_error "Échec de l'installation" - print_message "Vérifiez qu'un appareil est bien connecté : adb devices" fi fi fi diff --git a/app/android/.gitignore b/app/android/.gitignore old mode 100644 new mode 100755 diff --git a/app/android/app/proguard-rules.pro b/app/android/app/proguard-rules.pro old mode 100644 new mode 100755 diff --git a/app/android/app/src/main/kotlin/fr/geosector/app3/MainActivity.kt b/app/android/app/src/main/kotlin/fr/geosector/app3/MainActivity.kt old mode 100644 new mode 100755 diff --git a/app/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/app/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/app/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/app/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/app/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/app/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/app/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/app/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/app/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/app/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png old mode 100644 new mode 100755 diff --git a/app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml old mode 100644 new mode 100755 diff --git a/app/android/app/src/main/res/values/colors.xml b/app/android/app/src/main/res/values/colors.xml old mode 100644 new mode 100755 diff --git a/app/apple1.png b/app/apple1.png old mode 100644 new mode 100755 diff --git a/app/assets/fonts/InterVariable-Italic.ttf b/app/assets/fonts/InterVariable-Italic.ttf old mode 100644 new mode 100755 diff --git a/app/assets/fonts/InterVariable.ttf b/app/assets/fonts/InterVariable.ttf old mode 100644 new mode 100755 diff --git a/app/assets/icons/.gitkeep b/app/assets/icons/.gitkeep old mode 100644 new mode 100755 diff --git a/app/assets/images/icons/icon-1024.png b/app/assets/images/icons/icon-1024.png old mode 100644 new mode 100755 diff --git a/app/assets/images/logo-geosector-512.png b/app/assets/images/logo-geosector-512.png old mode 100644 new mode 100755 diff --git a/app/codemagic.yaml b/app/codemagic.yaml old mode 100644 new mode 100755 diff --git a/app/docs/CACHE-CLEANING-SYSTEM.md b/app/docs/CACHE-CLEANING-SYSTEM.md old mode 100644 new mode 100755 diff --git a/app/docs/CHAT-LOADING-OPTIMIZATION.md b/app/docs/CHAT-LOADING-OPTIMIZATION.md old mode 100644 new mode 100755 diff --git a/app/docs/CODEMAGIC-IOS.md b/app/docs/CODEMAGIC-IOS.md old mode 100644 new mode 100755 diff --git a/app/docs/Capture_membres_old_board_passages.png b/app/docs/Capture_membres_old_board_passages.png old mode 100644 new mode 100755 diff --git a/app/docs/FLOW-BOOT-APP.md b/app/docs/FLOW-BOOT-APP.md old mode 100644 new mode 100755 diff --git a/app/docs/FLOW-STRIPE.md b/app/docs/FLOW-STRIPE.md old mode 100644 new mode 100755 diff --git a/app/docs/FLUTTER-ANALYZE.md b/app/docs/FLUTTER-ANALYZE.md old mode 100644 new mode 100755 diff --git a/app/docs/GESTION-API-SECTORS.md b/app/docs/GESTION-API-SECTORS.md old mode 100644 new mode 100755 diff --git a/app/docs/GESTION-SECTEURS.md b/app/docs/GESTION-SECTEURS.md old mode 100644 new mode 100755 diff --git a/app/docs/PLANNING-STRIPE-FLUTTER.md b/app/docs/PLANNING-STRIPE-FLUTTER.md old mode 100644 new mode 100755 diff --git a/app/docs/QUEUE-APP-API.md b/app/docs/QUEUE-APP-API.md old mode 100644 new mode 100755 diff --git a/app/docs/SCAFFOLD-PLAN.md b/app/docs/SCAFFOLD-PLAN.md old mode 100644 new mode 100755 diff --git a/app/docs/STATISTICS-CROSS-FILTERING.md b/app/docs/STATISTICS-CROSS-FILTERING.md old mode 100644 new mode 100755 diff --git a/app/docs/STATISTICS-DUAL-FILTERS.md b/app/docs/STATISTICS-DUAL-FILTERS.md old mode 100644 new mode 100755 diff --git a/app/docs/STATISTICS-REAL-DATA.md b/app/docs/STATISTICS-REAL-DATA.md old mode 100644 new mode 100755 diff --git a/app/docs/STRIPE-BACKEND-MIGRATION.md b/app/docs/STRIPE-BACKEND-MIGRATION.md old mode 100644 new mode 100755 diff --git a/app/docs/STRIPE-MIGRATION-RESUME.md b/app/docs/STRIPE-MIGRATION-RESUME.md old mode 100644 new mode 100755 diff --git a/app/docs/TODO-APP.md b/app/docs/TODO-APP.md old mode 100644 new mode 100755 diff --git a/app/docs/TODO-ISOLATION-OPERATIONS.md b/app/docs/TODO-ISOLATION-OPERATIONS.md old mode 100644 new mode 100755 diff --git a/app/docs/TODO-MAP-CACHE-WEB.md b/app/docs/TODO-MAP-CACHE-WEB.md old mode 100644 new mode 100755 diff --git a/app/docs/connexions-api.md b/app/docs/connexions-api.md old mode 100644 new mode 100755 diff --git a/app/docs/contrat_hebergement_maintenance.odt b/app/docs/contrat_hebergement_maintenance.odt old mode 100644 new mode 100755 diff --git a/app/docs/emails.txt b/app/docs/emails.txt old mode 100644 new mode 100755 diff --git a/app/docs/geo_app_structure.sql b/app/docs/geo_app_structure.sql old mode 100644 new mode 100755 diff --git a/app/docs/geosector-structure.sql b/app/docs/geosector-structure.sql old mode 100644 new mode 100755 diff --git a/app/fastlane.log.ios b/app/fastlane.log.ios old mode 100644 new mode 100755 diff --git a/app/fastlane.logios b/app/fastlane.logios old mode 100644 new mode 100755 diff --git a/app/fastlane/Appfile b/app/fastlane/Appfile old mode 100644 new mode 100755 diff --git a/app/fastlane/Fastfile b/app/fastlane/Fastfile old mode 100644 new mode 100755 diff --git a/app/ios/.gitignore b/app/ios/.gitignore old mode 100644 new mode 100755 diff --git a/app/ios/ExportOptions.plist b/app/ios/ExportOptions.plist old mode 100644 new mode 100755 diff --git a/app/ios/Flutter/AppFrameworkInfo.plist b/app/ios/Flutter/AppFrameworkInfo.plist old mode 100644 new mode 100755 diff --git a/app/ios/Flutter/Debug.xcconfig b/app/ios/Flutter/Debug.xcconfig old mode 100644 new mode 100755 diff --git a/app/ios/Flutter/Release.xcconfig b/app/ios/Flutter/Release.xcconfig old mode 100644 new mode 100755 diff --git a/app/ios/GeoSector_v3_Development.mobileprovision b/app/ios/GeoSector_v3_Development.mobileprovision old mode 100644 new mode 100755 diff --git a/app/ios/Podfile b/app/ios/Podfile old mode 100644 new mode 100755 diff --git a/app/ios/Podfile.lock b/app/ios/Podfile.lock old mode 100644 new mode 100755 diff --git a/app/ios/Runner.xcodeproj/project.pbxproj b/app/ios/Runner.xcodeproj/project.pbxproj old mode 100644 new mode 100755 diff --git a/app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata old mode 100644 new mode 100755 diff --git a/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist old mode 100644 new mode 100755 diff --git a/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings old mode 100644 new mode 100755 diff --git a/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme old mode 100644 new mode 100755 diff --git a/app/ios/Runner.xcworkspace/contents.xcworkspacedata b/app/ios/Runner.xcworkspace/contents.xcworkspacedata old mode 100644 new mode 100755 diff --git a/app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist old mode 100644 new mode 100755 diff --git a/app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings old mode 100644 new mode 100755 diff --git a/app/ios/Runner/AppDelegate.swift b/app/ios/Runner/AppDelegate.swift old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Base.lproj/LaunchScreen.storyboard b/app/ios/Runner/Base.lproj/LaunchScreen.storyboard old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Base.lproj/Main.storyboard b/app/ios/Runner/Base.lproj/Main.storyboard old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Info.plist b/app/ios/Runner/Info.plist old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Runner-Bridging-Header.h b/app/ios/Runner/Runner-Bridging-Header.h old mode 100644 new mode 100755 diff --git a/app/ios/Runner/Runner.entitlements b/app/ios/Runner/Runner.entitlements old mode 100644 new mode 100755 diff --git a/app/ios/RunnerTests/RunnerTests.swift b/app/ios/RunnerTests/RunnerTests.swift old mode 100644 new mode 100755 diff --git a/app/lib/app.dart b/app/lib/app.dart index 58b784fd..6e7a39fe 100755 --- a/app/lib/app.dart +++ b/app/lib/app.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:geosector_app/core/theme/app_theme.dart'; -import 'package:geosector_app/core/services/theme_service.dart'; import 'package:go_router/go_router.dart'; // Import conditionnel pour le web import 'package:universal_html/html.dart' as html; @@ -38,7 +37,6 @@ final membreRepository = MembreRepository(); final amicaleRepository = AmicaleRepository(); final syncService = SyncService(userRepository: userRepository); final connectivityService = ConnectivityService(); -final themeService = ThemeService.instance; class GeosectorApp extends StatefulWidget { const GeosectorApp({super.key}); @@ -168,64 +166,56 @@ class _GeosectorAppState extends State with WidgetsBindingObserver @override Widget build(BuildContext context) { - return AnimatedBuilder( - animation: themeService, + return MaterialApp.router( + title: 'GeoSector', + theme: AppTheme.lightTheme, + // Pas de darkTheme - thème clair forcé pour éviter les problèmes d'affichage + themeMode: ThemeMode.light, + routerConfig: _createRouter(), + debugShowCheckedModeBanner: false, + // Builder pour appliquer le theme responsive à toute l'app builder: (context, child) { - return MaterialApp.router( - title: 'GeoSector', - theme: AppTheme.lightTheme, - darkTheme: AppTheme.darkTheme, - themeMode: themeService.themeMode, - routerConfig: _createRouter(), - debugShowCheckedModeBanner: false, - // Builder pour appliquer le theme responsive à toute l'app - builder: (context, child) { - return LayoutBuilder( - builder: (context, constraints) { - // Récupérer le theme actuel (clair ou sombre) - final brightness = Theme.of(context).brightness; - final textColor = brightness == Brightness.light - ? AppTheme.textLightColor - : AppTheme.textDarkColor; - - // Débogage en mode développement - final width = constraints.maxWidth; - final scaleFactor = AppTheme.getFontScaleFactor(width); - - // Afficher le debug uniquement lors du changement de taille - if (width < AppTheme.breakpointMobileSmall) { - debugPrint('📱 Mode: Très petit mobile (${width.toStringAsFixed(0)}px) → Facteur: ×$scaleFactor'); - } else if (width < AppTheme.breakpointMobile) { - debugPrint('📱 Mode: Mobile (${width.toStringAsFixed(0)}px) → Facteur: ×$scaleFactor'); - } else if (width < AppTheme.breakpointTablet) { - debugPrint('📱 Mode: Tablette (${width.toStringAsFixed(0)}px) → Facteur: ×$scaleFactor'); - } else { - debugPrint('🖥️ Mode: Desktop (${width.toStringAsFixed(0)}px) → Facteur: ×$scaleFactor'); - } - - // Appliquer le TextTheme responsive - return Theme( - data: Theme.of(context).copyWith( - textTheme: AppTheme.getResponsiveTextTheme(context, textColor), - ), - child: child ?? const SizedBox.shrink(), - ); - }, + return LayoutBuilder( + builder: (context, constraints) { + // Thème clair uniquement + const textColor = AppTheme.textLightColor; + + // Débogage en mode développement + final width = constraints.maxWidth; + final scaleFactor = AppTheme.getFontScaleFactor(width); + + // Afficher le debug uniquement lors du changement de taille + if (width < AppTheme.breakpointMobileSmall) { + debugPrint('📱 Mode: Très petit mobile (${width.toStringAsFixed(0)}px) → Facteur: ×$scaleFactor'); + } else if (width < AppTheme.breakpointMobile) { + debugPrint('📱 Mode: Mobile (${width.toStringAsFixed(0)}px) → Facteur: ×$scaleFactor'); + } else if (width < AppTheme.breakpointTablet) { + debugPrint('📱 Mode: Tablette (${width.toStringAsFixed(0)}px) → Facteur: ×$scaleFactor'); + } else { + debugPrint('🖥️ Mode: Desktop (${width.toStringAsFixed(0)}px) → Facteur: ×$scaleFactor'); + } + + // Appliquer le TextTheme responsive + return Theme( + data: Theme.of(context).copyWith( + textTheme: AppTheme.getResponsiveTextTheme(context, textColor), + ), + child: child ?? const SizedBox.shrink(), ); }, - // Configuration des localisations pour le français - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: const [ - Locale('fr', 'FR'), // Français comme langue principale - Locale('en', 'US'), // Anglais en fallback - ], - locale: const Locale('fr', 'FR'), // Forcer le français par défaut ); }, + // Configuration des localisations pour le français + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: const [ + Locale('fr', 'FR'), // Français comme langue principale + Locale('en', 'US'), // Anglais en fallback + ], + locale: const Locale('fr', 'FR'), // Forcer le français par défaut ); } diff --git a/app/lib/chat/TODO_CHAT.md b/app/lib/chat/TODO_CHAT.md old mode 100644 new mode 100755 diff --git a/app/lib/chat/chat_config.yaml b/app/lib/chat/chat_config.yaml old mode 100644 new mode 100755 diff --git a/app/lib/chat/example_usage.dart b/app/lib/chat/example_usage.dart old mode 100644 new mode 100755 diff --git a/app/lib/chat/models/message.dart b/app/lib/chat/models/message.dart old mode 100644 new mode 100755 diff --git a/app/lib/chat/models/message.g.dart b/app/lib/chat/models/message.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/chat/models/room.dart b/app/lib/chat/models/room.dart old mode 100644 new mode 100755 diff --git a/app/lib/chat/models/room.g.dart b/app/lib/chat/models/room.g.dart old mode 100644 new mode 100755 index eb03ecaf..077d57a4 --- a/app/lib/chat/models/room.g.dart +++ b/app/lib/chat/models/room.g.dart @@ -26,7 +26,7 @@ class RoomAdapter extends TypeAdapter { unreadCount: fields[6] as int, recentMessages: (fields[7] as List?) ?.map((dynamic e) => (e as Map).cast()) - .toList(), + ?.toList(), updatedAt: fields[8] as DateTime?, createdBy: fields[9] as int?, isSynced: fields[10] as bool, diff --git a/app/lib/chat/pages/rooms_page.dart b/app/lib/chat/pages/rooms_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/chat/pages/rooms_page_embedded.dart b/app/lib/chat/pages/rooms_page_embedded.dart old mode 100644 new mode 100755 diff --git a/app/lib/chat/services/chat_config_loader.dart b/app/lib/chat/services/chat_config_loader.dart old mode 100644 new mode 100755 diff --git a/app/lib/chat/services/chat_info_service.dart b/app/lib/chat/services/chat_info_service.dart old mode 100644 new mode 100755 diff --git a/app/lib/chat/services/chat_service.dart b/app/lib/chat/services/chat_service.dart old mode 100644 new mode 100755 diff --git a/app/lib/chat/widgets/recipient_selector.dart b/app/lib/chat/widgets/recipient_selector.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/constants/app_keys.dart b/app/lib/core/constants/app_keys.dart index eaafb0e7..090d36c7 100755 --- a/app/lib/core/constants/app_keys.dart +++ b/app/lib/core/constants/app_keys.dart @@ -155,7 +155,7 @@ class AppKeys { 'titres': 'À finaliser', 'titre': 'À finaliser', 'couleur1': 0xFFFFFFFF, // Blanc (nbPassages=0) - 'couleur2': 0xFFFFB978, // Orange moyen (nbPassages=1) + 'couleur2': 0xFFFF8C00, // Orange vif (nbPassages=1) 'couleur3': 0xFFE66F00, // Orange foncé (nbPassages>1) 'icon_data': Icons.refresh, }, diff --git a/app/lib/core/data/models/amicale_model.g.dart b/app/lib/core/data/models/amicale_model.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/client_model.g.dart b/app/lib/core/data/models/client_model.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/event_stats_model.dart b/app/lib/core/data/models/event_stats_model.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/membre_model.g.dart b/app/lib/core/data/models/membre_model.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/operation_model.g.dart b/app/lib/core/data/models/operation_model.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/passage_model.g.dart b/app/lib/core/data/models/passage_model.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/payment_link_result.dart b/app/lib/core/data/models/payment_link_result.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/pending_request.dart b/app/lib/core/data/models/pending_request.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/pending_request.g.dart b/app/lib/core/data/models/pending_request.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/region_model.g.dart b/app/lib/core/data/models/region_model.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/sector_model.g.dart b/app/lib/core/data/models/sector_model.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/user_model.g.dart b/app/lib/core/data/models/user_model.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/data/models/user_sector_model.g.dart b/app/lib/core/data/models/user_sector_model.g.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/app_info_service.dart b/app/lib/core/services/app_info_service.dart index 4d28fe2a..c906628b 100755 --- a/app/lib/core/services/app_info_service.dart +++ b/app/lib/core/services/app_info_service.dart @@ -1,19 +1,19 @@ // ⚠️ AUTO-GENERATED FILE - DO NOT EDIT MANUALLY // This file is automatically generated by deploy-app.sh script -// Last update: 2026-01-19 15:35:06 +// Last update: 2026-01-26 16:48:32 // Source: ../VERSION file // // GEOSECTOR App Version Service // Provides application version and build information without external dependencies class AppInfoService { - // Version number (format: x.x.x) - static const String version = '3.6.3'; + // Version number (format: YY.MM.DDNN - auto-incremented on each DEV deploy) + static const String version = '26.01.2605'; - // Build number (version without dots: xxx) - static const String buildNumber = '363'; + // Build number (version without dots: YYMMDDNN) + static const String buildNumber = '26012605'; - // Full version string (format: vx.x.x+xxx) + // Full version string (format: vYY.MM.DDNN+YYMMDDNN) static String get fullVersion => 'v$version+$buildNumber'; // Application name diff --git a/app/lib/core/services/chat_manager.dart b/app/lib/core/services/chat_manager.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/device_info_service.dart b/app/lib/core/services/device_info_service.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/event_stats_service.dart b/app/lib/core/services/event_stats_service.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/logger_service.dart b/app/lib/core/services/logger_service.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/stripe_connect_service.dart b/app/lib/core/services/stripe_connect_service.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/stripe_tap_to_pay_service.dart b/app/lib/core/services/stripe_tap_to_pay_service.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/stripe_terminal_service.dart b/app/lib/core/services/stripe_terminal_service.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/stripe_terminal_service_simple.dart b/app/lib/core/services/stripe_terminal_service_simple.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/temp_entity_service.dart b/app/lib/core/services/temp_entity_service.dart old mode 100644 new mode 100755 diff --git a/app/lib/core/services/theme_service.dart b/app/lib/core/services/theme_service.dart deleted file mode 100755 index 772ee1b2..00000000 --- a/app/lib/core/services/theme_service.dart +++ /dev/null @@ -1,191 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/scheduler.dart'; -import 'package:hive_flutter/hive_flutter.dart'; -import 'package:geosector_app/core/constants/app_keys.dart'; - -/// Service pour gérer les préférences de thème de l'application -/// Supporte la détection automatique du mode sombre/clair du système -/// Utilise Hive pour la persistance au lieu de SharedPreferences -class ThemeService extends ChangeNotifier { - static ThemeService? _instance; - static ThemeService get instance => _instance ??= ThemeService._(); - - ThemeService._() { - _init(); - } - - // Mode de thème actuel - ThemeMode _themeMode = ThemeMode.system; - - // Clé pour stocker les préférences dans Hive - static const String _themeModeKey = 'theme_mode'; - - /// Mode de thème actuel - ThemeMode get themeMode => _themeMode; - - /// Détecte si le système est en mode sombre - bool get isSystemDark { - final brightness = SchedulerBinding.instance.platformDispatcher.platformBrightness; - return brightness == Brightness.dark; - } - - /// Détermine si l'app doit utiliser le mode sombre - bool get isDarkMode { - switch (_themeMode) { - case ThemeMode.light: - return false; - case ThemeMode.dark: - return true; - case ThemeMode.system: - return isSystemDark; - } - } - - /// Initialise le service - Future _init() async { - try { - await _loadThemeMode(); - - // Observer les changements du système - SchedulerBinding.instance.platformDispatcher.onPlatformBrightnessChanged = () { - _onSystemBrightnessChanged(); - }; - - debugPrint('🎨 ThemeService initialisé - Mode: $_themeMode, Système sombre: $isSystemDark'); - } catch (e) { - debugPrint('❌ Erreur initialisation ThemeService: $e'); - } - } - - /// Charge le mode de thème depuis Hive - Future _loadThemeMode() async { - try { - // Vérifier si la box settings est ouverte - if (!Hive.isBoxOpen(AppKeys.settingsBoxName)) { - debugPrint('⚠️ Box settings pas encore ouverte, utilisation du mode système par défaut'); - _themeMode = ThemeMode.system; - return; - } - - final settingsBox = Hive.box(AppKeys.settingsBoxName); - final savedMode = settingsBox.get(_themeModeKey) as String?; - - if (savedMode != null) { - _themeMode = ThemeMode.values.firstWhere( - (mode) => mode.name == savedMode, - orElse: () => ThemeMode.system, - ); - debugPrint('🎨 Mode de thème chargé depuis Hive: $_themeMode'); - } else { - debugPrint('🎨 Aucun mode de thème sauvegardé, utilisation du mode système'); - } - } catch (e) { - debugPrint('❌ Erreur chargement thème: $e'); - _themeMode = ThemeMode.system; - } - } - - /// Sauvegarde le mode de thème dans Hive - Future _saveThemeMode() async { - try { - // Vérifier si la box settings est ouverte - if (!Hive.isBoxOpen(AppKeys.settingsBoxName)) { - debugPrint('⚠️ Box settings pas ouverte, impossible de sauvegarder le thème'); - return; - } - - final settingsBox = Hive.box(AppKeys.settingsBoxName); - await settingsBox.put(_themeModeKey, _themeMode.name); - debugPrint('💾 Mode de thème sauvegardé dans Hive: $_themeMode'); - } catch (e) { - debugPrint('❌ Erreur sauvegarde thème: $e'); - } - } - - /// Appelée quand la luminosité du système change - void _onSystemBrightnessChanged() { - if (_themeMode == ThemeMode.system) { - debugPrint('🌗 Changement luminosité système détecté - Sombre: $isSystemDark'); - notifyListeners(); - } - } - - /// Change le mode de thème - Future setThemeMode(ThemeMode mode) async { - if (_themeMode != mode) { - _themeMode = mode; - await _saveThemeMode(); - notifyListeners(); - debugPrint('🎨 Mode de thème changé: $mode'); - } - } - - /// Basculer entre clair et sombre - Future toggleTheme() async { - switch (_themeMode) { - case ThemeMode.light: - await setThemeMode(ThemeMode.dark); - break; - case ThemeMode.dark: - await setThemeMode(ThemeMode.light); - break; - case ThemeMode.system: - // Si système, basculer vers l'opposé du mode actuel du système - await setThemeMode(isSystemDark ? ThemeMode.light : ThemeMode.dark); - break; - } - } - - /// Retourner au mode système - Future useSystemTheme() async { - await setThemeMode(ThemeMode.system); - } - - /// Forcer le mode clair - Future useLightTheme() async { - await setThemeMode(ThemeMode.light); - } - - /// Forcer le mode sombre - Future useDarkTheme() async { - await setThemeMode(ThemeMode.dark); - } - - /// Obtenir une description textuelle du mode actuel - String get themeModeDescription { - switch (_themeMode) { - case ThemeMode.light: - return 'Clair'; - case ThemeMode.dark: - return 'Sombre'; - case ThemeMode.system: - return 'Automatique (${isSystemDark ? 'sombre' : 'clair'})'; - } - } - - /// Obtenir l'icône appropriée pour le mode actuel - IconData get themeModeIcon { - switch (_themeMode) { - case ThemeMode.light: - return Icons.light_mode; - case ThemeMode.dark: - return Icons.dark_mode; - case ThemeMode.system: - return Icons.brightness_auto; - } - } - - /// Recharge le thème depuis Hive (utile après l'ouverture des boxes) - Future reloadFromHive() async { - await _loadThemeMode(); - notifyListeners(); - debugPrint('🔄 ThemeService rechargé depuis Hive'); - } - - /// Réinitialise le service au mode système - void reset() { - _themeMode = ThemeMode.system; - notifyListeners(); - debugPrint('🔄 ThemeService réinitialisé'); - } -} \ No newline at end of file diff --git a/app/lib/core/utils/html_stub.dart b/app/lib/core/utils/html_stub.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/admin/admin_connexions_page.dart b/app/lib/presentation/admin/admin_connexions_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/auth/splash_page.dart b/app/lib/presentation/auth/splash_page.dart index d3050429..46f85d45 100755 --- a/app/lib/presentation/auth/splash_page.dart +++ b/app/lib/presentation/auth/splash_page.dart @@ -78,11 +78,8 @@ class _SplashPageState extends State with SingleTickerProviderStateM /// Effectue un nettoyage sélectif du cache /// Préserve la box pending_requests et les données critiques Future _performSelectiveCleanup({bool manual = false}) async { - debugPrint('🧹 === DÉBUT DU NETTOYAGE DU CACHE === 🧹'); - debugPrint('📌 Type: ${manual ? "MANUEL" : "AUTOMATIQUE"}'); - debugPrint('📱 Platform: ${kIsWeb ? "WEB" : "MOBILE"}'); - debugPrint('📦 Version actuelle: $_appVersion'); - + debugPrint('🧹 Nettoyage du cache (${manual ? "manuel" : "auto"})...'); + try { if (mounted) { setState(() { @@ -94,27 +91,21 @@ class _SplashPageState extends State with SingleTickerProviderStateM // Étape 1: Nettoyer le Service Worker (Web uniquement) if (kIsWeb) { - debugPrint('🔄 Nettoyage du Service Worker...'); try { - // Désenregistrer tous les service workers final registrations = await html.window.navigator.serviceWorker?.getRegistrations(); if (registrations != null) { for (final registration in registrations) { await registration.unregister(); - debugPrint('✅ Service Worker désenregistré'); } } - - // Nettoyer les caches du navigateur if (html.window.caches != null) { final cacheNames = await html.window.caches!.keys(); for (final cacheName in cacheNames) { await html.window.caches!.delete(cacheName); - debugPrint('✅ Cache "$cacheName" supprimé'); } } } catch (e) { - debugPrint('⚠️ Erreur lors du nettoyage Service Worker: $e'); + debugPrint('⚠️ Erreur Service Worker: $e'); } } @@ -126,28 +117,20 @@ class _SplashPageState extends State with SingleTickerProviderStateM } // Étape 2: Sauvegarder les données critiques (pending_requests + app_version) - debugPrint('💾 Sauvegarde des données critiques...'); List? pendingRequests; String? savedAppVersion; try { - // Sauvegarder pending_requests if (Hive.isBoxOpen(AppKeys.pendingRequestsBoxName)) { final pendingBox = Hive.box(AppKeys.pendingRequestsBoxName); pendingRequests = pendingBox.values.toList(); - debugPrint('📊 ${pendingRequests.length} requêtes en attente sauvegardées'); await pendingBox.close(); } - - // Sauvegarder app_version pour éviter de perdre l'info de version if (Hive.isBoxOpen(AppKeys.settingsBoxName)) { final settingsBox = Hive.box(AppKeys.settingsBoxName); savedAppVersion = settingsBox.get('app_version') as String?; - if (savedAppVersion != null) { - debugPrint('📦 Version sauvegardée: $savedAppVersion'); - } } } catch (e) { - debugPrint('⚠️ Erreur lors de la sauvegarde: $e'); + debugPrint('⚠️ Erreur sauvegarde données critiques: $e'); } if (mounted) { @@ -173,17 +156,14 @@ class _SplashPageState extends State with SingleTickerProviderStateM ]; // Étape 4: Fermer et supprimer les boxes - debugPrint('🗑️ Nettoyage des boxes Hive...'); for (final boxName in boxesToClean) { try { if (Hive.isBoxOpen(boxName)) { await Hive.box(boxName).close(); - debugPrint('📦 Box "$boxName" fermée'); } await Hive.deleteBoxFromDisk(boxName); - debugPrint('✅ Box "$boxName" supprimée'); } catch (e) { - debugPrint('⚠️ Erreur lors du nettoyage de "$boxName": $e'); + debugPrint('⚠️ Erreur nettoyage box "$boxName": $e'); } } @@ -195,27 +175,21 @@ class _SplashPageState extends State with SingleTickerProviderStateM } // Étape 5: Réinitialiser Hive proprement - debugPrint('🔄 Réinitialisation de Hive...'); await Hive.close(); await Future.delayed(const Duration(milliseconds: 500)); await Hive.initFlutter(); // Étape 6: Restaurer les données critiques if (pendingRequests != null && pendingRequests.isNotEmpty) { - debugPrint('♻️ Restauration des requêtes en attente...'); final pendingBox = await Hive.openBox(AppKeys.pendingRequestsBoxName); for (final request in pendingRequests) { await pendingBox.add(request); } - debugPrint('✅ ${pendingRequests.length} requêtes restaurées'); } - // Restaurer app_version pour maintenir la détection de changement de version if (savedAppVersion != null) { - debugPrint('♻️ Restauration de la version...'); final settingsBox = await Hive.openBox(AppKeys.settingsBoxName); await settingsBox.put('app_version', savedAppVersion); - debugPrint('✅ Version restaurée: $savedAppVersion'); } if (mounted) { @@ -225,7 +199,7 @@ class _SplashPageState extends State with SingleTickerProviderStateM }); } - debugPrint('🎉 === NETTOYAGE TERMINÉ AVEC SUCCÈS === 🎉'); + debugPrint('✅ Nettoyage du cache terminé'); // Petit délai pour voir le message de succès await Future.delayed(const Duration(milliseconds: 500)); @@ -238,7 +212,7 @@ class _SplashPageState extends State with SingleTickerProviderStateM } } catch (e) { - debugPrint('❌ ERREUR CRITIQUE lors du nettoyage: $e'); + debugPrint('❌ Erreur nettoyage cache: $e'); if (mounted) { setState(() { _isCleaningCache = false; @@ -260,45 +234,29 @@ class _SplashPageState extends State with SingleTickerProviderStateM /// Réinitialise le cache de tous les repositories après nettoyage complet void _resetAllRepositoriesCache() { try { - debugPrint('🔄 === RESET DU CACHE DES REPOSITORIES === 🔄'); - - // Reset du cache des 3 repositories qui utilisent le pattern de cache passageRepository.resetCache(); sectorRepository.resetCache(); membreRepository.resetCache(); - - debugPrint('✅ Cache de tous les repositories réinitialisé'); } catch (e) { - debugPrint('⚠️ Erreur lors du reset des caches: $e'); - // Ne pas faire échouer le processus si le reset échoue + debugPrint('⚠️ Erreur reset caches repositories: $e'); } } /// Détecte et gère le refresh (F5) avec session existante /// Retourne true si une session a été restaurée, false sinon Future _handleSessionRefreshIfNeeded() async { - if (!kIsWeb) { - debugPrint('📱 Plateforme mobile - pas de gestion F5'); - return false; - } + if (!kIsWeb) return false; try { - debugPrint('🔍 Vérification d\'une session existante (F5)...'); - - // Charger l'utilisateur depuis Hive await CurrentUserService.instance.loadFromHive(); final isLoggedIn = CurrentUserService.instance.isLoggedIn; final displayMode = CurrentUserService.instance.displayMode; final sessionId = CurrentUserService.instance.sessionId; - if (!isLoggedIn || sessionId == null) { - debugPrint('ℹ️ Aucune session active - affichage normal de la splash'); - return false; - } + if (!isLoggedIn || sessionId == null) return false; - debugPrint('🔄 Session active détectée - mode: $displayMode'); - debugPrint('🔄 Rechargement des données depuis l\'API...'); + debugPrint('🔄 Session active détectée, restauration...'); if (mounted) { setState(() { @@ -312,9 +270,6 @@ class _SplashPageState extends State with SingleTickerProviderStateM // Appeler le nouvel endpoint API pour restaurer la session // IMPORTANT: Utiliser getWithoutQueue() pour ne JAMAIS mettre cette requête en file d'attente - // Les refresh de session sont liés à une session spécifique et ne doivent pas être rejoués - debugPrint('🔄 Appel API: user/session avec sessionId: ${sessionId.substring(0, 10)}...'); - final response = await ApiService.instance.getWithoutQueue( 'user/session', queryParameters: {'mode': displayMode}, @@ -327,10 +282,7 @@ class _SplashPageState extends State with SingleTickerProviderStateM if (response.data is String) { final dataStr = response.data as String; if (dataStr.contains(' with SingleTickerProviderStateM switch (statusCode) { case 200: - // Succès - traiter les données if (data == null || data['success'] != true) { - debugPrint('❌ Format de réponse invalide (200 mais pas success=true)'); + debugPrint('❌ Format de réponse session invalide'); await CurrentUserService.instance.clearUser(); return false; } - debugPrint('✅ Données reçues de l\'API, traitement...'); - if (mounted) { setState(() { _statusMessage = "Chargement de vos données..."; @@ -356,7 +305,6 @@ class _SplashPageState extends State with SingleTickerProviderStateM }); } - // Traiter les données avec DataLoadingService final apiData = data['data'] as Map?; if (apiData == null) { debugPrint('❌ Données manquantes dans la réponse'); @@ -365,11 +313,9 @@ class _SplashPageState extends State with SingleTickerProviderStateM } await DataLoadingService.instance.processLoginData(apiData); - debugPrint('✅ Session restaurée avec succès'); break; case 400: - // Paramètre mode invalide - erreur technique debugPrint('❌ Paramètre mode invalide: $displayMode'); await CurrentUserService.instance.clearUser(); if (mounted) { @@ -380,8 +326,7 @@ class _SplashPageState extends State with SingleTickerProviderStateM return false; case 401: - // Session invalide ou expirée - debugPrint('⚠️ Session invalide ou expirée'); + debugPrint('⚠️ Session expirée'); await CurrentUserService.instance.clearUser(); if (mounted) { setState(() { @@ -391,9 +336,8 @@ class _SplashPageState extends State with SingleTickerProviderStateM return false; case 403: - // Accès interdit (membre → admin) ou entité inactive final message = data?['message'] ?? 'Accès interdit'; - debugPrint('🚫 Accès interdit: $message'); + debugPrint('❌ Accès interdit: $message'); await CurrentUserService.instance.clearUser(); if (mounted) { setState(() { @@ -410,7 +354,6 @@ class _SplashPageState extends State with SingleTickerProviderStateM return false; case 500: - // Erreur serveur final message = data?['message'] ?? 'Erreur serveur'; debugPrint('❌ Erreur serveur: $message'); if (mounted) { @@ -425,11 +368,9 @@ class _SplashPageState extends State with SingleTickerProviderStateM ), ); } - // Ne pas effacer la session en cas d'erreur serveur return false; default: - // Code de retour inattendu debugPrint('❌ Code HTTP inattendu: $statusCode'); await CurrentUserService.instance.clearUser(); return false; @@ -449,12 +390,11 @@ class _SplashPageState extends State with SingleTickerProviderStateM if (!mounted) return true; if (displayMode == 'admin') { - debugPrint('🔀 Redirection vers interface admin'); context.go('/admin/home'); } else { - debugPrint('🔀 Redirection vers interface user'); context.go('/user/field-mode'); } + debugPrint('✅ Session restaurée → $displayMode'); return true; @@ -477,53 +417,32 @@ class _SplashPageState extends State with SingleTickerProviderStateM /// Vérifie si une nouvelle version est disponible et nettoie si nécessaire Future _checkVersionAndCleanIfNeeded() async { - if (!kIsWeb) { - debugPrint('📱 Plateforme mobile - pas de nettoyage automatique'); - return; - } + if (!kIsWeb) return; try { String lastVersion = ''; - - // Lire la version depuis Hive settings if (Hive.isBoxOpen(AppKeys.settingsBoxName)) { final settingsBox = Hive.box(AppKeys.settingsBoxName); lastVersion = settingsBox.get('app_version', defaultValue: '') as String; } - debugPrint('🔍 Vérification de version:'); - debugPrint(' Version stockée: $lastVersion'); - debugPrint(' Version actuelle: $_appVersion'); - - // Si changement de version détecté if (lastVersion.isNotEmpty && lastVersion != _appVersion) { - debugPrint('🆕 NOUVELLE VERSION DÉTECTÉE !'); - debugPrint(' Migration de $lastVersion vers $_appVersion'); - + debugPrint('🆕 Nouvelle version: $lastVersion → $_appVersion'); if (mounted) { setState(() { _statusMessage = "Nouvelle version détectée, mise à jour..."; }); } - - // Effectuer le nettoyage automatique await _performSelectiveCleanup(manual: false); - - // Reset du cache des repositories après nettoyage _resetAllRepositoriesCache(); } else if (lastVersion.isEmpty) { - // Première installation - debugPrint('🎉 Première installation détectée'); if (Hive.isBoxOpen(AppKeys.settingsBoxName)) { final settingsBox = Hive.box(AppKeys.settingsBoxName); await settingsBox.put('app_version', _appVersion); - debugPrint('💾 Version initiale sauvegardée dans Hive: $_appVersion'); } - } else { - debugPrint('✅ Même version - pas de nettoyage nécessaire'); } } catch (e) { - debugPrint('⚠️ Erreur lors de la vérification de version: $e'); + debugPrint('⚠️ Erreur vérification version: $e'); } } @@ -560,7 +479,7 @@ class _SplashPageState extends State with SingleTickerProviderStateM void _startInitialization() async { try { - debugPrint('🚀 Début de l\'initialisation complète de l\'application...'); + debugPrint('🚀 Initialisation de l\'application...'); // Étape 1: Vérification des permissions GPS (obligatoire) - 0 à 10% if (!kIsWeb) { @@ -577,7 +496,6 @@ class _SplashPageState extends State with SingleTickerProviderStateM final errorMessage = await LocationService.getLocationErrorMessage(); if (!hasPermission) { - // Si les permissions ne sont pas accordées, on arrête tout debugPrint('❌ Permissions GPS refusées'); if (mounted) { setState(() { @@ -616,10 +534,7 @@ class _SplashPageState extends State with SingleTickerProviderStateM } // === GESTION F5 WEB : Vérifier session AVANT de détruire les données === - // Sur Web, on essaie d'abord de récupérer une session existante if (kIsWeb) { - debugPrint('🌐 Web détecté - tentative de récupération de session existante...'); - if (mounted) { setState(() { _statusMessage = "Vérification de session..."; @@ -627,12 +542,9 @@ class _SplashPageState extends State with SingleTickerProviderStateM }); } - // Initialisation légère qui préserve les données final hasExistingSession = await HiveService.instance.initializeWithoutReset(); if (hasExistingSession) { - debugPrint('✅ Session existante détectée, tentative de restauration...'); - if (mounted) { setState(() { _statusMessage = "Restauration de la session..."; @@ -640,17 +552,8 @@ class _SplashPageState extends State with SingleTickerProviderStateM }); } - // Tenter la restauration via l'API final sessionRestored = await _handleSessionRefreshIfNeeded(); - if (sessionRestored) { - debugPrint('✅ Session restaurée via F5 - fin de l\'initialisation'); - return; - } - - // Si la restauration API échoue, on continue vers le login - debugPrint('⚠️ Restauration API échouée, passage au login normal'); - } else { - debugPrint('ℹ️ Pas de session existante, initialisation normale'); + if (sessionRestored) return; } } @@ -689,22 +592,11 @@ class _SplashPageState extends State with SingleTickerProviderStateM // Gérer la box pending_requests séparément pour préserver les données try { - debugPrint('📦 Gestion de la box pending_requests...'); if (!Hive.isBoxOpen(AppKeys.pendingRequestsBoxName)) { - // Importer PendingRequest si nécessaire - final pendingRequestBox = await Hive.openBox(AppKeys.pendingRequestsBoxName); - final pendingCount = pendingRequestBox.length; - if (pendingCount > 0) { - debugPrint('⏳ $pendingCount requêtes en attente trouvées dans la box'); - } else { - debugPrint('✅ Box pending_requests ouverte (vide)'); - } - } else { - debugPrint('✅ Box pending_requests déjà ouverte'); + await Hive.openBox(AppKeys.pendingRequestsBoxName); } } catch (e) { - debugPrint('⚠️ Erreur lors de l\'ouverture de la box pending_requests: $e'); - // On continue quand même, ce n'est pas critique pour le démarrage + debugPrint('⚠️ Erreur ouverture pending_requests: $e'); } if (mounted) { @@ -717,8 +609,7 @@ class _SplashPageState extends State with SingleTickerProviderStateM // Étape 4: Vérification finale - 80 à 95% final allBoxesOpen = HiveService.instance.areAllBoxesOpen(); if (!allBoxesOpen) { - final diagnostic = HiveService.instance.getDiagnostic(); - debugPrint('❌ Diagnostic des Box: $diagnostic'); + debugPrint('❌ Erreur: certaines boxes Hive non ouvertes'); throw Exception('Une erreur est survenue lors de l\'initialisation'); } @@ -744,10 +635,9 @@ class _SplashPageState extends State with SingleTickerProviderStateM final settingsBox = Hive.box(AppKeys.settingsBoxName); await settingsBox.put('hive_initialized', true); await settingsBox.put('hive_initialized_at', DateTime.now().toIso8601String()); - debugPrint('✅ Clé hive_initialized définie à true dans settings'); } } catch (e) { - debugPrint('⚠️ Impossible de définir la clé hive_initialized: $e'); + debugPrint('⚠️ Erreur hive_initialized: $e'); } // Attendre un court instant pour que l'utilisateur voie "Application prête !" @@ -761,39 +651,59 @@ class _SplashPageState extends State with SingleTickerProviderStateM if (widget.action != null) { await _handleAutoRedirect(); } else { - setState(() { - _showButtons = true; - }); + // Sur mobile natif ou petit écran, rediriger directement vers connexion utilisateur + // L'interface admin n'est disponible que sur Web avec grand écran + if (mounted) { + final screenWidth = MediaQuery.of(context).size.width; + final isSmallScreen = screenWidth < 600; + + if (!kIsWeb || isSmallScreen) { + context.go('/login/user'); + } else { + setState(() { + _showButtons = true; + }); + } + } } } - debugPrint('✅ Initialisation complète de l\'application terminée avec succès'); + debugPrint('✅ Initialisation terminée'); } catch (e) { - debugPrint('❌ Erreur lors de l\'initialisation: $e'); + debugPrint('❌ Erreur initialisation: $e'); if (mounted) { setState(() { _statusMessage = "Erreur de chargement - Veuillez redémarrer l'application"; _progress = 1.0; _isInitializing = false; - _showButtons = true; }); + + // Sur mobile natif ou petit écran, rediriger vers connexion utilisateur même en cas d'erreur + // L'interface admin n'est disponible que sur Web avec grand écran + final screenWidth = MediaQuery.of(context).size.width; + final isSmallScreen = screenWidth < 600; + + if (!kIsWeb || isSmallScreen) { + context.go('/login/user'); + } else { + setState(() { + _showButtons = true; + }); + } } } } /// Gère la redirection automatique après l'initialisation Future _handleAutoRedirect() async { - // Petit délai pour voir le message "Application prête !" await Future.delayed(const Duration(milliseconds: 300)); - + if (!mounted) return; final action = widget.action?.toLowerCase(); final type = widget.type?.toLowerCase(); - debugPrint('🔄 Redirection automatique: action=$action, type=$type'); - // Afficher un message de redirection avant de naviguer setState(() { _statusMessage = action == 'login' @@ -805,8 +715,8 @@ class _SplashPageState extends State with SingleTickerProviderStateM await Future.delayed(const Duration(milliseconds: 200)); - if (!context.mounted) return; - + if (!mounted) return; + switch (action) { case 'login': if (type == 'admin') { @@ -1227,7 +1137,6 @@ class _SplashPageState extends State with SingleTickerProviderStateM ); if (confirm == true) { - debugPrint('👤 Utilisateur a demandé un nettoyage manuel'); await _performSelectiveCleanup(manual: true); // Reset du cache des repositories après nettoyage diff --git a/app/lib/presentation/chat/chat_communication_page.dart b/app/lib/presentation/chat/chat_communication_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/dialogs/sector_action_result_dialog.dart b/app/lib/presentation/dialogs/sector_action_result_dialog.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/dialogs/sector_dialog.dart b/app/lib/presentation/dialogs/sector_dialog.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/pages/amicale_page.dart b/app/lib/presentation/pages/amicale_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/pages/connexions_page.dart b/app/lib/presentation/pages/connexions_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/pages/field_mode_page.dart b/app/lib/presentation/pages/field_mode_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/pages/home_page.dart b/app/lib/presentation/pages/home_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/pages/messages_page.dart b/app/lib/presentation/pages/messages_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/pages/operations_page.dart b/app/lib/presentation/pages/operations_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/settings/theme_settings_page.dart b/app/lib/presentation/settings/theme_settings_page.dart deleted file mode 100755 index 322a1abd..00000000 --- a/app/lib/presentation/settings/theme_settings_page.dart +++ /dev/null @@ -1,341 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:geosector_app/core/services/theme_service.dart'; -import 'package:geosector_app/presentation/widgets/theme_switcher.dart'; - -/// Page de paramètres pour la gestion du thème -class ThemeSettingsPage extends StatelessWidget { - const ThemeSettingsPage({super.key}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return Scaffold( - appBar: AppBar( - title: const Text('Paramètres d\'affichage'), - backgroundColor: theme.colorScheme.surface, - foregroundColor: theme.colorScheme.onSurface, - ), - body: SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Section informations - _buildInfoSection(context), - const SizedBox(height: 32), - - // Section sélection du thème - _buildThemeSection(context), - const SizedBox(height: 32), - - // Section aperçu - _buildPreviewSection(context), - ], - ), - ), - ); - } - - Widget _buildInfoSection(BuildContext context) { - final theme = Theme.of(context); - - return Card( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(Icons.info_outline, color: theme.colorScheme.primary), - const SizedBox(width: 8), - Text( - 'À propos des thèmes', - style: theme.textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 12), - const Text( - '• Mode Automatique : Suit les préférences de votre système\n' - '• Mode Clair : Interface claire en permanence\n' - '• Mode Sombre : Interface sombre en permanence\n\n' - 'Le mode automatique détecte automatiquement si votre appareil ' - 'est configuré en mode sombre ou clair et adapte l\'interface en conséquence.', - ), - ], - ), - ), - ); - } - - Widget _buildThemeSection(BuildContext context) { - final theme = Theme.of(context); - - return Card( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(Icons.palette_outlined, color: theme.colorScheme.primary), - const SizedBox(width: 8), - Text( - 'Choix du thème', - style: theme.textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 16), - - // Thème actuel - AnimatedBuilder( - animation: ThemeService.instance, - builder: (context, child) { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: theme.colorScheme.primaryContainer.withOpacity(0.3), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: theme.colorScheme.primary.withOpacity(0.3), - ), - ), - child: Row( - children: [ - Icon( - ThemeService.instance.themeModeIcon, - color: theme.colorScheme.primary, - ), - const SizedBox(width: 12), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Thème actuel', - style: theme.textTheme.bodySmall, - ), - Text( - ThemeService.instance.themeModeDescription, - style: theme.textTheme.bodyLarge?.copyWith( - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ], - ), - ); - }, - ), - - const SizedBox(height: 24), - - // Boutons de sélection style segments - Text( - 'Sélectionner un thème :', - style: theme.textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 12), - - Center( - child: ThemeSwitcher( - style: ThemeSwitcherStyle.segmentedButton, - onThemeChanged: () { - // Optionnel: feedback haptic ou autres actions - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - 'Thème changé vers ${ThemeService.instance.themeModeDescription}'), - duration: const Duration(seconds: 2), - ), - ); - }, - ), - ), - - const SizedBox(height: 16), - - // Options alternatives - Text( - 'Autres options :', - style: theme.textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 8), - - // Dropdown - const Row( - children: [ - Text('Menu déroulant : '), - ThemeSwitcher( - style: ThemeSwitcherStyle.dropdown, - showLabel: true, - ), - ], - ), - - const SizedBox(height: 8), - - // Toggle buttons - const Row( - children: [ - Text('Boutons : '), - ThemeSwitcher(style: ThemeSwitcherStyle.toggleButtons), - ], - ), - ], - ), - ), - ); - } - - Widget _buildPreviewSection(BuildContext context) { - final theme = Theme.of(context); - - return Card( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(Icons.preview, color: theme.colorScheme.primary), - const SizedBox(width: 8), - Text( - 'Aperçu des couleurs', - style: theme.textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - ], - ), - const SizedBox(height: 16), - - // Grille de couleurs - GridView.count( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - crossAxisCount: 4, - mainAxisSpacing: 8, - crossAxisSpacing: 8, - children: [ - _buildColorSample('Primary', theme.colorScheme.primary, - theme.colorScheme.onPrimary), - _buildColorSample('Secondary', theme.colorScheme.secondary, - theme.colorScheme.onSecondary), - _buildColorSample('Surface', theme.colorScheme.surface, - theme.colorScheme.onSurface), - _buildColorSample('Background', theme.colorScheme.surface, - theme.colorScheme.onSurface), - ], - ), - - const SizedBox(height: 16), - - // Exemples de composants - Text( - 'Exemples de composants :', - style: theme.textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.w500, - ), - ), - const SizedBox(height: 12), - - Wrap( - spacing: 8, - runSpacing: 8, - children: [ - ElevatedButton( - onPressed: () {}, - child: const Text('Bouton'), - ), - OutlinedButton( - onPressed: () {}, - child: const Text('Bouton'), - ), - TextButton( - onPressed: () {}, - child: const Text('Bouton'), - ), - const Chip( - label: Text('Chip'), - avatar: Icon(Icons.star, size: 16), - ), - ], - ), - ], - ), - ), - ); - } - - Widget _buildColorSample(String label, Color color, Color onColor) { - return Container( - height: 60, - decoration: BoxDecoration( - color: color, - borderRadius: BorderRadius.circular(8), - border: Border.all(color: Colors.grey.withOpacity(0.3)), - ), - child: Center( - child: Text( - label, - style: TextStyle( - color: onColor, - fontSize: 12, - fontWeight: FontWeight.w500, - ), - textAlign: TextAlign.center, - ), - ), - ); - } -} - -/// Dialog simple pour les paramètres de thème -class ThemeSettingsDialog extends StatelessWidget { - const ThemeSettingsDialog({super.key}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - - return AlertDialog( - title: Row( - children: [ - Icon(Icons.palette_outlined, color: theme.colorScheme.primary), - const SizedBox(width: 8), - const Text('Apparence'), - ], - ), - content: const Column( - mainAxisSize: MainAxisSize.min, - children: [ - ThemeInfo(), - SizedBox(height: 16), - ThemeSwitcher( - style: ThemeSwitcherStyle.segmentedButton, - ), - ], - ), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: const Text('Fermer'), - ), - ], - ); - } -} diff --git a/app/lib/presentation/user/user_field_mode_page.dart b/app/lib/presentation/user/user_field_mode_page.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/badged_navigation_destination.dart b/app/lib/presentation/widgets/badged_navigation_destination.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/btn_passages.dart b/app/lib/presentation/widgets/btn_passages.dart old mode 100644 new mode 100755 index e6752c2d..37952dbf --- a/app/lib/presentation/widgets/btn_passages.dart +++ b/app/lib/presentation/widgets/btn_passages.dart @@ -193,7 +193,8 @@ class BtnPassages extends StatelessWidget { Text( total > 1 ? 'passages' : 'passage', style: TextStyle( - fontSize: 10, + fontSize: 11, + fontWeight: FontWeight.w500, color: Colors.grey[700], ), textAlign: TextAlign.center, @@ -297,7 +298,8 @@ class BtnPassages extends StatelessWidget { child: Text( titre, style: const TextStyle( - fontSize: 10, + fontSize: 11, + fontWeight: FontWeight.w500, color: Colors.white, ), textAlign: TextAlign.center, @@ -371,9 +373,9 @@ class BtnPassages extends StatelessWidget { Text( 'Nouveau', style: TextStyle( - fontSize: 10, + fontSize: 11, + fontWeight: FontWeight.w500, color: Colors.grey[700], - fontWeight: FontWeight.w600, ), textAlign: TextAlign.center, ), diff --git a/app/lib/presentation/widgets/grouped_passages_dialog.dart b/app/lib/presentation/widgets/grouped_passages_dialog.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/loading_spin_overlay.dart b/app/lib/presentation/widgets/loading_spin_overlay.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/members_board_passages.dart b/app/lib/presentation/widgets/members_board_passages.dart old mode 100644 new mode 100755 index 4cab5d3f..34d28650 --- a/app/lib/presentation/widgets/members_board_passages.dart +++ b/app/lib/presentation/widgets/members_board_passages.dart @@ -402,14 +402,14 @@ class _MembersBoardPassagesState extends State { child: Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(vertical: 8), - color: Colors.green.withOpacity(0.2), + color: Color(AppKeys.typesPassages[1]!['couleur2'] as int).withOpacity(0.2), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.task_alt, size: 16, - color: Colors.green, + color: Color(AppKeys.typesPassages[1]!['couleur2'] as int), ), const SizedBox(width: 4), _buildHeaderText('Effectués', 2, headerStyle), @@ -436,14 +436,14 @@ class _MembersBoardPassagesState extends State { child: Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(vertical: 8), - color: Colors.orange.withOpacity(0.2), + color: Color(AppKeys.typesPassages[2]!['couleur2'] as int).withOpacity(0.2), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.refresh, size: 16, - color: Colors.orange, + color: Color(AppKeys.typesPassages[2]!['couleur2'] as int), ), const SizedBox(width: 4), _buildHeaderText('À finaliser', 4, headerStyle), @@ -460,14 +460,14 @@ class _MembersBoardPassagesState extends State { child: Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(vertical: 8), - color: Colors.red.withOpacity(0.2), + color: Color(AppKeys.typesPassages[3]!['couleur2'] as int).withOpacity(0.2), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.block, size: 16, - color: Colors.red, + color: Color(AppKeys.typesPassages[3]!['couleur2'] as int), ), const SizedBox(width: 4), _buildHeaderText('Refusés', 5, headerStyle), @@ -484,14 +484,14 @@ class _MembersBoardPassagesState extends State { child: Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(vertical: 8), - color: Colors.lightBlue.withOpacity(0.2), + color: Color(AppKeys.typesPassages[4]!['couleur2'] as int).withOpacity(0.2), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.volunteer_activism, size: 16, - color: Colors.lightBlue, + color: Color(AppKeys.typesPassages[4]!['couleur2'] as int), ), const SizedBox(width: 4), _buildHeaderText('Dons', 6, headerStyle), @@ -509,14 +509,14 @@ class _MembersBoardPassagesState extends State { child: Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(vertical: 8), - color: Colors.blue.withOpacity(0.2), + color: Color(AppKeys.typesPassages[5]!['couleur2'] as int).withOpacity(0.2), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.layers, size: 16, - color: Colors.blue, + color: Color(AppKeys.typesPassages[5]!['couleur2'] as int), ), const SizedBox(width: 4), _buildHeaderText('Lots', 7, headerStyle), @@ -533,14 +533,14 @@ class _MembersBoardPassagesState extends State { child: Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(vertical: 8), - color: Colors.grey.withOpacity(0.2), + color: Color(AppKeys.typesPassages[6]!['couleur2'] as int).withOpacity(0.2), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.home_outlined, size: 16, - color: Colors.grey, + color: Color(AppKeys.typesPassages[6]!['couleur2'] as int), ), const SizedBox(width: 4), _buildHeaderText('Vides', showLotType ? 8 : 7, headerStyle), @@ -712,7 +712,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.green.withOpacity(0.2), + color: Color(AppKeys.typesPassages[1]!['couleur2'] as int), alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -752,7 +752,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.orange.withOpacity(0.2), + color: Color(AppKeys.typesPassages[2]!['couleur2'] as int), alignment: Alignment.center, child: Text( aFinaliserCount.toString(), @@ -773,7 +773,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.red.withOpacity(0.2), + color: Color(AppKeys.typesPassages[3]!['couleur2'] as int), alignment: Alignment.center, child: Text( refuseCount.toString(), @@ -794,7 +794,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.lightBlue.withOpacity(0.2), + color: Color(AppKeys.typesPassages[4]!['couleur2'] as int), alignment: Alignment.center, child: Text( donCount.toString(), @@ -816,7 +816,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.blue.withOpacity(0.2), + color: Color(AppKeys.typesPassages[5]!['couleur2'] as int), alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -846,7 +846,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.grey.withOpacity(0.2), + color: Color(AppKeys.typesPassages[6]!['couleur2'] as int), alignment: Alignment.center, child: Text( videCount.toString(), @@ -1074,7 +1074,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.green.withOpacity(0.1), + color: Color(AppKeys.typesPassages[1]!['couleur2'] as int).withOpacity(0.8), alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -1109,7 +1109,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.orange.withOpacity(0.1), + color: Color(AppKeys.typesPassages[2]!['couleur2'] as int).withOpacity(0.8), alignment: Alignment.center, child: Text( aFinaliserCount.toString(), @@ -1130,7 +1130,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.red.withOpacity(0.1), + color: Color(AppKeys.typesPassages[3]!['couleur2'] as int).withOpacity(0.8), alignment: Alignment.center, child: Text( refuseCount.toString(), @@ -1150,7 +1150,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.lightBlue.withOpacity(0.1), + color: Color(AppKeys.typesPassages[4]!['couleur2'] as int).withOpacity(0.8), alignment: Alignment.center, child: Text( donCount.toString(), @@ -1171,7 +1171,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.blue.withOpacity(0.1), + color: Color(AppKeys.typesPassages[5]!['couleur2'] as int).withOpacity(0.8), alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -1201,7 +1201,7 @@ class _MembersBoardPassagesState extends State { child: Container( width: double.infinity, height: double.infinity, - color: Colors.grey.withOpacity(0.1), + color: Color(AppKeys.typesPassages[6]!['couleur2'] as int).withOpacity(0.8), alignment: Alignment.center, child: Text( videCount.toString(), diff --git a/app/lib/presentation/widgets/offline_test_button.dart b/app/lib/presentation/widgets/offline_test_button.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/passage_form_dialog.dart b/app/lib/presentation/widgets/passage_form_dialog.dart index db16bb11..aaec83ff 100755 --- a/app/lib/presentation/widgets/passage_form_dialog.dart +++ b/app/lib/presentation/widgets/passage_form_dialog.dart @@ -89,17 +89,13 @@ class _PassageFormDialogState extends State { // Helpers de validation String? _validateNumero(String? value) { - debugPrint('🔍 [VALIDATOR] _validateNumero appelé avec: "$value"'); if (value == null || value.trim().isEmpty) { - debugPrint('❌ [VALIDATOR] Numéro vide -> retourne erreur'); return 'Le numéro est obligatoire'; } final numero = int.tryParse(value.trim()); if (numero == null || numero <= 0) { - debugPrint('❌ [VALIDATOR] Numéro invalide: $value -> retourne erreur'); return 'Numéro invalide'; } - debugPrint('✅ [VALIDATOR] Numéro valide: $numero'); return null; } @@ -166,30 +162,11 @@ class _PassageFormDialogState extends State { super.initState(); try { - debugPrint('=== DEBUT PassageFormDialog.initState ==='); - // Accéder à la settingsBox (déjà ouverte dans l'app) _settingsBox = Hive.box(AppKeys.settingsBoxName); // Initialize controllers with passage data if available final passage = widget.passage; - debugPrint('Passage reçu: ${passage != null}'); - - if (passage != null) { - debugPrint('Passage ID: ${passage.id}'); - debugPrint('Passage fkType: ${passage.fkType}'); - debugPrint('Passage numero: ${passage.numero}'); - debugPrint('Passage rueBis: ${passage.rueBis}'); - debugPrint('Passage rue: ${passage.rue}'); - debugPrint('Passage ville: ${passage.ville}'); - debugPrint('Passage name: ${passage.name}'); - debugPrint('Passage email: ${passage.email}'); - debugPrint('Passage phone: ${passage.phone}'); - debugPrint('Passage montant: ${passage.montant}'); - debugPrint('Passage remarque: ${passage.remarque}'); - debugPrint('Passage fkHabitat: ${passage.fkHabitat}'); - debugPrint('Passage fkTypeReglement: ${passage.fkTypeReglement}'); - } _selectedPassageType = passage?.fkType; _showForm = false; // Toujours commencer par la sélection de type @@ -199,8 +176,6 @@ class _PassageFormDialogState extends State { // Section Adresse : ouverte si nouveau passage, fermée si modification _isAddressSectionExpanded = passage == null; - debugPrint('Initialisation des controllers...'); - // S'assurer que toutes les valeurs null deviennent des chaînes vides String numero = passage?.numero.toString() ?? ''; String rueBis = passage?.rueBis.toString() ?? ''; @@ -222,7 +197,6 @@ class _PassageFormDialogState extends State { // Si nouveau passage, charger les valeurs mémorisées de la dernière adresse if (passage == null) { - debugPrint('Nouveau passage: chargement des valeurs mémorisées...'); numero = _settingsBox.get('lastPassageNumero', defaultValue: '') as String; rueBis = _settingsBox.get('lastPassageRueBis', defaultValue: '') as String; rue = _settingsBox.get('lastPassageRue', defaultValue: '') as String; @@ -231,8 +205,6 @@ class _PassageFormDialogState extends State { _fkHabitat = _settingsBox.get('lastPassageFkHabitat', defaultValue: 1) as int; appt = _settingsBox.get('lastPassageAppt', defaultValue: '') as String; niveau = _settingsBox.get('lastPassageNiveau', defaultValue: '') as String; - - debugPrint('Valeurs chargées: numero="$numero", rue="$rue", ville="$ville"'); } // Initialiser la date de passage @@ -242,20 +214,6 @@ class _PassageFormDialogState extends State { final String timeFormatted = '${_passedAt.hour.toString().padLeft(2, '0')}:${_passedAt.minute.toString().padLeft(2, '0')}'; - debugPrint('Valeurs pour controllers:'); - debugPrint(' numero: "$numero"'); - debugPrint(' rueBis: "$rueBis"'); - debugPrint(' rue: "$rue"'); - debugPrint(' ville: "$ville"'); - debugPrint(' name: "$name"'); - debugPrint(' email: "$email"'); - debugPrint(' phone: "$phone"'); - debugPrint(' montant: "$montant"'); - debugPrint(' remarque: "$remarque"'); - debugPrint(' passedAt: "$_passedAt"'); - debugPrint(' dateFormatted: "$dateFormatted"'); - debugPrint(' timeFormatted: "$timeFormatted"'); - _numeroController = TextEditingController(text: numero); _rueBisController = TextEditingController(text: rueBis); _rueController = TextEditingController(text: rue); @@ -280,12 +238,8 @@ class _PassageFormDialogState extends State { }); } }); - - debugPrint('=== FIN PassageFormDialog.initState ==='); } catch (e, stackTrace) { - debugPrint('=== ERREUR PassageFormDialog.initState ==='); - debugPrint('Erreur: $e'); - debugPrint('StackTrace: $stackTrace'); + debugPrint('❌ Erreur initState PassageFormDialog: $e\n$stackTrace'); rethrow; } } @@ -334,20 +288,11 @@ class _PassageFormDialogState extends State { } void _handleSubmit() async { - debugPrint('🔵 [SUBMIT] Début _handleSubmit'); - - if (_isSubmitting) { - debugPrint('⚠️ [SUBMIT] Déjà en cours de soumission, abandon'); - return; - } - - debugPrint('🔵 [SUBMIT] Vérification de l\'état du formulaire'); - debugPrint('🔵 [SUBMIT] _formKey: $_formKey'); - debugPrint('🔵 [SUBMIT] _formKey.currentState: ${_formKey.currentState}'); + if (_isSubmitting) return; // Validation avec protection contre le null if (_formKey.currentState == null) { - debugPrint('❌ [SUBMIT] ERREUR: _formKey.currentState est null !'); + debugPrint('❌ _formKey.currentState est null'); if (mounted) { await ResultDialog.show( context: context, @@ -358,14 +303,9 @@ class _PassageFormDialogState extends State { return; } - debugPrint('🔵 [SUBMIT] Validation du formulaire...'); final isValid = _formKey.currentState!.validate(); - debugPrint('🔵 [SUBMIT] Résultat validation: $isValid'); if (!isValid) { - debugPrint('⚠️ [SUBMIT] Validation échouée, abandon'); - - // Afficher un dialog d'erreur clair à l'utilisateur if (mounted) { await ResultDialog.show( context: context, @@ -376,109 +316,73 @@ class _PassageFormDialogState extends State { return; } - debugPrint('✅ [SUBMIT] Validation OK, appel _savePassage()'); await _savePassage(); - debugPrint('🔵 [SUBMIT] Fin _handleSubmit'); } Future _savePassage() async { - debugPrint('🟢 [SAVE] Début _savePassage'); + if (_isSubmitting) return; - if (_isSubmitting) { - debugPrint('⚠️ [SAVE] Déjà en cours de soumission, abandon'); - return; - } - - debugPrint('🟢 [SAVE] Mise à jour état _isSubmitting = true'); setState(() { _isSubmitting = true; }); - // Afficher l'overlay de chargement - debugPrint('🟢 [SAVE] Affichage overlay de chargement'); final overlay = LoadingSpinOverlayUtils.show( context: context, message: 'Enregistrement en cours...', ); try { - debugPrint('🟢 [SAVE] Récupération utilisateur actuel'); final currentUser = widget.userRepository.getCurrentUser(); - debugPrint('🟢 [SAVE] currentUser: ${currentUser?.id} - ${currentUser?.name}'); if (currentUser == null) { - debugPrint('❌ [SAVE] ERREUR: Utilisateur non connecté'); throw Exception("Utilisateur non connecté"); } - debugPrint('🟢 [SAVE] Récupération opération active'); final currentOperation = widget.operationRepository.getCurrentOperation(); - debugPrint('🟢 [SAVE] currentOperation: ${currentOperation?.id} - ${currentOperation?.name}'); if (currentOperation == null && widget.passage == null) { - debugPrint('❌ [SAVE] ERREUR: Aucune opération active trouvée'); throw Exception("Aucune opération active trouvée"); } // Déterminer les valeurs de montant et type de règlement selon le type de passage - debugPrint('🟢 [SAVE] Calcul des valeurs finales'); - debugPrint('🟢 [SAVE] _selectedPassageType: $_selectedPassageType'); - final String finalMontant = (_selectedPassageType == 1 || _selectedPassageType == 5) ? _montantController.text.trim().replaceAll(',', '.') : '0'; - debugPrint('🟢 [SAVE] finalMontant: $finalMontant'); // Déterminer le type de règlement final selon le type de passage final int finalTypeReglement; if (_selectedPassageType == 1 || _selectedPassageType == 5) { - // Pour les types 1 et 5, utiliser la valeur sélectionnée (qui a été validée) finalTypeReglement = _fkTypeReglement; } else { - // Pour tous les autres types, forcer "Non renseigné" finalTypeReglement = 4; } - debugPrint('🟢 [SAVE] finalTypeReglement: $finalTypeReglement'); // Déterminer la valeur de nbPassages selon le type de passage final int finalNbPassages; if (widget.passage != null) { - // Modification d'un passage existant if (_selectedPassageType == 2) { - // Type 2 (À finaliser) : toujours incrémenter finalNbPassages = widget.passage!.nbPassages + 1; } else { - // Autres types : mettre à 1 si actuellement 0, sinon conserver final currentNbPassages = widget.passage!.nbPassages; finalNbPassages = currentNbPassages == 0 ? 1 : currentNbPassages; } } else { - // Nouveau passage : toujours 1 finalNbPassages = 1; } - debugPrint('🟢 [SAVE] finalNbPassages: $finalNbPassages'); // Récupérer les coordonnées GPS pour un nouveau passage String finalGpsLat = '0.0'; String finalGpsLng = '0.0'; if (widget.passage == null) { - // Nouveau passage : tenter de récupérer la position GPS actuelle - debugPrint('🟢 [SAVE] Récupération de la position GPS...'); try { final position = await LocationService.getCurrentPosition(); if (position != null) { finalGpsLat = position.latitude.toString(); finalGpsLng = position.longitude.toString(); - debugPrint('🟢 [SAVE] GPS récupéré: lat=$finalGpsLat, lng=$finalGpsLng'); - } else { - debugPrint('🟢 [SAVE] GPS non disponible, utilisation de 0.0 (l\'API utilisera le géocodage)'); } - } catch (e) { - debugPrint('⚠️ [SAVE] Erreur récupération GPS: $e - l\'API utilisera le géocodage'); - } + } catch (_) {} } else { - // Modification : conserver les coordonnées existantes finalGpsLat = widget.passage!.gpsLat; finalGpsLng = widget.passage!.gpsLng; } @@ -537,38 +441,25 @@ class _PassageFormDialogState extends State { isSynced: false, ); - // Sauvegarder le passage d'abord - debugPrint('🟢 [SAVE] Préparation sauvegarde passage'); + // Sauvegarder le passage PassageModel? savedPassage; if (widget.passage == null || widget.passage!.id == 0) { - // Création d'un nouveau passage (passage null OU id=0) - debugPrint('🟢 [SAVE] Création d\'un nouveau passage'); savedPassage = await widget.passageRepository.createPassageWithReturn(passageData); - debugPrint('🟢 [SAVE] Passage créé avec ID: ${savedPassage?.id}'); - if (savedPassage == null) { - debugPrint('❌ [SAVE] ERREUR: savedPassage est null après création'); throw Exception("Échec de la création du passage"); } } else { - // Mise à jour d'un passage existant - debugPrint('🟢 [SAVE] Mise à jour passage existant ID: ${widget.passage!.id}'); await widget.passageRepository.updatePassage(passageData); - debugPrint('🟢 [SAVE] Mise à jour réussie'); savedPassage = passageData; } - // Garantir le type non-nullable après la vérification final confirmedPassage = savedPassage; - debugPrint('✅ [SAVE] Passage sauvegardé avec succès ID: ${confirmedPassage.id}'); // Mémoriser l'adresse pour la prochaine création de passage - debugPrint('🟢 [SAVE] Mémorisation adresse'); await _saveLastPassageAddress(); // Propager la résidence aux autres passages de l'immeuble si nécessaire if (_fkHabitat == 2 && _residenceController.text.trim().isNotEmpty) { - debugPrint('🟢 [SAVE] Propagation résidence à l\'immeuble'); await _propagateResidenceToBuilding(confirmedPassage); } @@ -605,16 +496,12 @@ class _PassageFormDialogState extends State { final paymentSuccess = await _attemptTapToPayWithPassage(confirmedPassage, montant); if (paymentSuccess) { - // Fermer le formulaire en cas de succès if (mounted) { Navigator.of(context, rootNavigator: false).pop(); widget.onSuccess?.call(); } - } else { - debugPrint('⚠️ Paiement Tap to Pay échoué - formulaire reste ouvert'); - // Ne pas fermer le formulaire en cas d'échec - // L'utilisateur peut réessayer ou annuler } + // Si échec, le formulaire reste ouvert pour réessayer }, onQRCodeCompleted: () { // Pour QR Code: fermer le formulaire après l'affichage du QR @@ -667,17 +554,10 @@ class _PassageFormDialogState extends State { } } } catch (e, stackTrace) { - // Masquer le loading - debugPrint('❌ [SAVE] ERREUR CAPTURÉE'); - debugPrint('❌ [SAVE] Type erreur: ${e.runtimeType}'); - debugPrint('❌ [SAVE] Message erreur: $e'); - debugPrint('❌ [SAVE] Stack trace:\n$stackTrace'); - + debugPrint('❌ Erreur sauvegarde passage: $e\n$stackTrace'); LoadingSpinOverlayUtils.hideSpecific(overlay); - // Afficher l'erreur final errorMessage = ApiException.fromError(e).message; - debugPrint('❌ [SAVE] Message d\'erreur formaté: $errorMessage'); if (mounted) { await ResultDialog.show( @@ -687,23 +567,17 @@ class _PassageFormDialogState extends State { ); } } finally { - debugPrint('🟢 [SAVE] Bloc finally - Nettoyage'); if (mounted) { setState(() { _isSubmitting = false; }); - debugPrint('🟢 [SAVE] _isSubmitting = false'); } - debugPrint('🟢 [SAVE] Fin _savePassage'); } } /// Mémoriser l'adresse du passage pour la prochaine création Future _saveLastPassageAddress() async { try { - debugPrint('🟡 [ADDRESS] Début mémorisation adresse'); - debugPrint('🟡 [ADDRESS] _settingsBox.isOpen: ${_settingsBox.isOpen}'); - await _settingsBox.put('lastPassageNumero', _numeroController.text.trim()); await _settingsBox.put('lastPassageRueBis', _rueBisController.text.trim()); await _settingsBox.put('lastPassageRue', _rueController.text.trim()); @@ -712,61 +586,34 @@ class _PassageFormDialogState extends State { await _settingsBox.put('lastPassageFkHabitat', _fkHabitat); await _settingsBox.put('lastPassageAppt', _apptController.text.trim()); await _settingsBox.put('lastPassageNiveau', _niveauController.text.trim()); - - debugPrint('✅ [ADDRESS] Adresse mémorisée avec succès'); - } catch (e, stackTrace) { - debugPrint('❌ [ADDRESS] Erreur lors de la mémorisation: $e'); - debugPrint('❌ [ADDRESS] Stack trace:\n$stackTrace'); + } catch (e) { + debugPrint('❌ Erreur mémorisation adresse: $e'); } } /// Propager la résidence aux autres passages de l'immeuble (fkType=2, même adresse, résidence vide) Future _propagateResidenceToBuilding(PassageModel savedPassage) async { try { - debugPrint('🟡 [PROPAGATE] Début propagation résidence'); - final passagesBox = Hive.box(AppKeys.passagesBoxName); - debugPrint('🟡 [PROPAGATE] passagesBox.isOpen: ${passagesBox.isOpen}'); - debugPrint('🟡 [PROPAGATE] passagesBox.length: ${passagesBox.length}'); - final residence = _residenceController.text.trim(); - debugPrint('🟡 [PROPAGATE] résidence: "$residence"'); - - // Clé d'adresse du passage sauvegardé final addressKey = '${savedPassage.numero}|${savedPassage.rueBis}|${savedPassage.rue}|${savedPassage.ville}'; - debugPrint('🟡 [PROPAGATE] addressKey: "$addressKey"'); - int updatedCount = 0; - - // Parcourir tous les passages for (int i = 0; i < passagesBox.length; i++) { final passage = passagesBox.getAt(i); if (passage != null) { - // Vérifier les critères final passageAddressKey = '${passage.numero}|${passage.rueBis}|${passage.rue}|${passage.ville}'; - if (passage.id != savedPassage.id && // Pas le passage actuel - passage.fkHabitat == 2 && // Appartement - passageAddressKey == addressKey && // Même adresse - passage.residence.trim().isEmpty) { // Résidence vide - - debugPrint('🟡 [PROPAGATE] Mise à jour passage ID: ${passage.id}'); - // Mettre à jour la résidence dans Hive + if (passage.id != savedPassage.id && + passage.fkHabitat == 2 && + passageAddressKey == addressKey && + passage.residence.trim().isEmpty) { final updatedPassage = passage.copyWith(residence: residence); await passagesBox.put(passage.key, updatedPassage); - updatedCount++; } } } - - if (updatedCount > 0) { - debugPrint('✅ [PROPAGATE] Résidence propagée à $updatedCount passage(s)'); - } else { - debugPrint('✅ [PROPAGATE] Aucun passage à mettre à jour'); - } - } catch (e, stackTrace) { - debugPrint('❌ [PROPAGATE] Erreur lors de la propagation: $e'); - debugPrint('❌ [PROPAGATE] Stack trace:\n$stackTrace'); + } catch (e) { + debugPrint('❌ Erreur propagation résidence: $e'); } } @@ -780,24 +627,110 @@ class _PassageFormDialogState extends State { if (currentUser != null && currentUser.fkEntite != null) { final userAmicale = widget.amicaleRepository.getAmicaleById(currentUser.fkEntite!); if (userAmicale != null) { - // Si chkLotActif = false (0), on ne doit pas afficher le type Lot (5) showLotType = userAmicale.chkLotActif; - debugPrint('Amicale ${userAmicale.name}: chkLotActif = $showLotType'); } } // Filtrer les types de passages en fonction de chkLotActif final filteredTypes = Map>.from(AppKeys.typesPassages); if (!showLotType) { - filteredTypes.remove(5); // Retirer le type "Lot" si chkLotActif = 0 - debugPrint('Type Lot (5) masqué car chkLotActif = false'); + filteredTypes.remove(5); } return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + // Afficher les infos du passage si modification + if (widget.passage != null) ...[ + // Adresse du passage + Container( + width: double.infinity, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: theme.colorScheme.primary.withOpacity(0.05), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: theme.colorScheme.primary.withOpacity(0.2), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Adresse principale + Text( + '${widget.passage!.numero} ${widget.passage!.rueBis} ${widget.passage!.rue}'.trim().replaceAll(RegExp(r'\s+'), ' '), + style: theme.textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 4), + Text( + widget.passage!.ville, + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.colorScheme.onSurface.withOpacity(0.7), + ), + ), + // Infos appartement si fkHabitat == 2 + if (widget.passage!.fkHabitat == 2) ...[ + const SizedBox(height: 8), + Row( + children: [ + if (widget.passage!.niveau.isNotEmpty) ...[ + Icon(Icons.stairs, size: 16, color: theme.colorScheme.primary), + const SizedBox(width: 4), + Text('Niveau ${widget.passage!.niveau}'), + const SizedBox(width: 12), + ], + if (widget.passage!.appt.isNotEmpty) ...[ + Icon(Icons.door_front_door, size: 16, color: theme.colorScheme.primary), + const SizedBox(width: 4), + Text('Appt ${widget.passage!.appt}'), + ], + ], + ), + ], + // Afficher le nom de l'habitant (pour maison et appartement) + if (widget.passage!.name.isNotEmpty) ...[ + const SizedBox(height: 8), + Row( + children: [ + Icon(Icons.person, size: 16, color: theme.colorScheme.primary), + const SizedBox(width: 4), + Expanded(child: Text(widget.passage!.name)), + ], + ), + ], + // Afficher la remarque si renseignée + if (widget.passage!.remarque.isNotEmpty) ...[ + const SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon(Icons.note, size: 16, color: theme.colorScheme.primary), + const SizedBox(width: 4), + Expanded( + child: Text( + widget.passage!.remarque, + style: theme.textTheme.bodySmall?.copyWith( + fontStyle: FontStyle.italic, + color: theme.colorScheme.onSurface.withOpacity(0.7), + ), + ), + ), + ], + ), + ], + ], + ), + ), + const SizedBox(height: 16), + const Divider(), + const SizedBox(height: 16), + ], Text( - 'Type de passage', + widget.passage != null + ? 'Choisir le nouveau type de ce passage' + : 'Type de passage', style: theme.textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, color: theme.colorScheme.primary, @@ -810,7 +743,7 @@ class _PassageFormDialogState extends State { gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: - MediaQuery.of(context).size.width < 600 ? 1.8 : 2.5, + MediaQuery.of(context).size.width < 600 ? 1.4 : 2.5, crossAxisSpacing: 12, mainAxisSpacing: 12, ), @@ -821,7 +754,6 @@ class _PassageFormDialogState extends State { final typeData = filteredTypes[typeId]; if (typeData == null) { - debugPrint('ERREUR: typeData null pour typeId: $typeId'); return const SizedBox(); } @@ -881,8 +813,7 @@ class _PassageFormDialogState extends State { ), ), ); - } catch (e) { - debugPrint('ERREUR dans itemBuilder pour index $index: $e'); + } catch (_) { return const SizedBox(); } }, @@ -893,9 +824,6 @@ class _PassageFormDialogState extends State { Widget _buildPassageForm() { try { - debugPrint('=== DEBUT _buildPassageForm ==='); - - debugPrint('Building Form...'); return Form( key: _formKey, child: Column( @@ -1362,11 +1290,8 @@ class _PassageFormDialogState extends State { ], ), ); - } catch (e, stackTrace) { - debugPrint('=== ERREUR _buildPassageForm ==='); - debugPrint('Erreur: $e'); - debugPrint('StackTrace: $stackTrace'); - + } catch (e) { + debugPrint('❌ Erreur _buildPassageForm: $e'); return Container( padding: const EdgeInsets.all(16), child: Column( @@ -1526,17 +1451,10 @@ class _PassageFormDialogState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (!_showForm) ...[ - () { - debugPrint('Building passage type selection...'); - return _buildPassageTypeSelection(); - }(), - ] else ...[ - () { - debugPrint('Building passage form...'); - return _buildPassageForm(); - }(), - ], + if (!_showForm) + _buildPassageTypeSelection() + else + _buildPassageForm(), ], ), ); @@ -1690,10 +1608,9 @@ class _PassageFormDialogState extends State { ); // Envoyer la mise à jour à l'API (sera fait de manière asynchrone) - widget.passageRepository.updatePassage(updatedPassage).then((_) { - debugPrint('✅ Passage mis à jour avec stripe_payment_id: $paymentIntentId'); - }).catchError((error) { - debugPrint('❌ Erreur mise à jour passage: $error'); + widget.passageRepository.updatePassage(updatedPassage).catchError((error) { + debugPrint('❌ Erreur mise à jour passage stripe: $error'); + return false; }); setState(() { @@ -1720,7 +1637,7 @@ class _PassageFormDialogState extends State { return false; } catch (e) { - debugPrint('Erreur Tap to Pay: $e'); + debugPrint('❌ Erreur Tap to Pay: $e'); if (mounted) { await ResultDialog.show( context: context, @@ -1735,10 +1652,7 @@ class _PassageFormDialogState extends State { @override Widget build(BuildContext context) { try { - debugPrint('=== DEBUT PassageFormDialog.build ==='); - final isMobile = _isMobile(context); - debugPrint('Platform mobile détectée: $isMobile'); if (isMobile) { // Mode plein écran pour mobile @@ -1786,12 +1700,8 @@ class _PassageFormDialogState extends State { ), ); } - } catch (e, stackTrace) { - debugPrint('=== ERREUR PassageFormDialog.build ==='); - debugPrint('Erreur: $e'); - debugPrint('StackTrace: $stackTrace'); - - // Retourner un widget d'erreur simple + } catch (e) { + debugPrint('❌ Erreur PassageFormDialog.build: $e'); return Dialog( child: Container( padding: const EdgeInsets.all(16), @@ -1980,9 +1890,7 @@ class _TapToPayFlowDialogState extends State<_TapToPayFlowDialog> { // Annuler le PaymentIntent si créé pour permettre une nouvelle tentative if (shouldCancelPayment && _paymentIntentId != null) { - StripeTapToPayService.instance.cancelPayment(_paymentIntentId!).catchError((cancelError) { - debugPrint('⚠️ Erreur annulation PaymentIntent: $cancelError'); - }); + StripeTapToPayService.instance.cancelPayment(_paymentIntentId!).catchError((_) {}); } setState(() { diff --git a/app/lib/presentation/widgets/passage_map_dialog.dart b/app/lib/presentation/widgets/passage_map_dialog.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/payment_method_selection_dialog.dart b/app/lib/presentation/widgets/payment_method_selection_dialog.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/pending_requests_counter.dart b/app/lib/presentation/widgets/pending_requests_counter.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/qr_code_payment_dialog.dart b/app/lib/presentation/widgets/qr_code_payment_dialog.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/result_dialog.dart b/app/lib/presentation/widgets/result_dialog.dart old mode 100644 new mode 100755 diff --git a/app/lib/presentation/widgets/theme_switcher.dart b/app/lib/presentation/widgets/theme_switcher.dart deleted file mode 100755 index 0b6cb0e9..00000000 --- a/app/lib/presentation/widgets/theme_switcher.dart +++ /dev/null @@ -1,231 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:geosector_app/core/services/theme_service.dart'; - -/// Widget pour basculer entre les thèmes clair/sombre/automatique -class ThemeSwitcher extends StatelessWidget { - /// Style d'affichage du sélecteur - final ThemeSwitcherStyle style; - - /// Afficher le texte descriptif - final bool showLabel; - - /// Callback optionnel appelé après changement de thème - final VoidCallback? onThemeChanged; - - const ThemeSwitcher({ - super.key, - this.style = ThemeSwitcherStyle.iconButton, - this.showLabel = false, - this.onThemeChanged, - }); - - @override - Widget build(BuildContext context) { - return AnimatedBuilder( - animation: ThemeService.instance, - builder: (context, child) { - switch (style) { - case ThemeSwitcherStyle.iconButton: - return _buildIconButton(context); - case ThemeSwitcherStyle.dropdown: - return _buildDropdown(context); - case ThemeSwitcherStyle.segmentedButton: - return _buildSegmentedButton(context); - case ThemeSwitcherStyle.toggleButtons: - return _buildToggleButtons(context); - } - }, - ); - } - - /// Bouton icône simple (bascule entre clair/sombre) - Widget _buildIconButton(BuildContext context) { - final themeService = ThemeService.instance; - - return IconButton( - icon: Icon(themeService.themeModeIcon), - tooltip: 'Changer le thème (${themeService.themeModeDescription})', - onPressed: () async { - await themeService.toggleTheme(); - onThemeChanged?.call(); - }, - ); - } - - /// Dropdown avec toutes les options - Widget _buildDropdown(BuildContext context) { - final themeService = ThemeService.instance; - final theme = Theme.of(context); - - return DropdownButton( - value: themeService.themeMode, - icon: Icon(Icons.arrow_drop_down, color: theme.colorScheme.onSurface), - underline: Container(), - items: [ - DropdownMenuItem( - value: ThemeMode.system, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.brightness_auto, size: 20), - const SizedBox(width: 8), - const Text('Automatique'), - if (showLabel) ...[ - const SizedBox(width: 4), - Text( - '(${themeService.isSystemDark ? 'sombre' : 'clair'})', - style: theme.textTheme.bodySmall, - ), - ], - ], - ), - ), - const DropdownMenuItem( - value: ThemeMode.light, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.light_mode, size: 20), - SizedBox(width: 8), - Text('Clair'), - ], - ), - ), - const DropdownMenuItem( - value: ThemeMode.dark, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.dark_mode, size: 20), - SizedBox(width: 8), - Text('Sombre'), - ], - ), - ), - ], - onChanged: (ThemeMode? mode) async { - if (mode != null) { - await themeService.setThemeMode(mode); - onThemeChanged?.call(); - } - }, - ); - } - - /// Boutons segmentés (Material 3) - Widget _buildSegmentedButton(BuildContext context) { - final themeService = ThemeService.instance; - - return SegmentedButton( - segments: const [ - ButtonSegment( - value: ThemeMode.light, - icon: Icon(Icons.light_mode, size: 16), - label: Text('Clair'), - ), - ButtonSegment( - value: ThemeMode.system, - icon: Icon(Icons.brightness_auto, size: 16), - label: Text('Auto'), - ), - ButtonSegment( - value: ThemeMode.dark, - icon: Icon(Icons.dark_mode, size: 16), - label: Text('Sombre'), - ), - ], - selected: {themeService.themeMode}, - onSelectionChanged: (Set selection) async { - if (selection.isNotEmpty) { - await themeService.setThemeMode(selection.first); - onThemeChanged?.call(); - } - }, - ); - } - - /// Boutons à bascule - Widget _buildToggleButtons(BuildContext context) { - final themeService = ThemeService.instance; - - return ToggleButtons( - borderRadius: BorderRadius.circular(8), - constraints: const BoxConstraints(minHeight: 40, minWidth: 60), - isSelected: [ - themeService.themeMode == ThemeMode.light, - themeService.themeMode == ThemeMode.system, - themeService.themeMode == ThemeMode.dark, - ], - onPressed: (int index) async { - final modes = [ThemeMode.light, ThemeMode.system, ThemeMode.dark]; - await themeService.setThemeMode(modes[index]); - onThemeChanged?.call(); - }, - children: const [ - Icon(Icons.light_mode, size: 20), - Icon(Icons.brightness_auto, size: 20), - Icon(Icons.dark_mode, size: 20), - ], - ); - } -} - -/// Widget d'information sur le thème actuel -class ThemeInfo extends StatelessWidget { - const ThemeInfo({super.key}); - - @override - Widget build(BuildContext context) { - return AnimatedBuilder( - animation: ThemeService.instance, - builder: (context, child) { - final themeService = ThemeService.instance; - final theme = Theme.of(context); - - return Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - decoration: BoxDecoration( - color: theme.colorScheme.surfaceContainerHighest.withOpacity(0.5), - borderRadius: BorderRadius.circular(8), - border: Border.all( - color: theme.colorScheme.outline.withOpacity(0.3), - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - themeService.themeModeIcon, - size: 16, - color: theme.colorScheme.primary, - ), - const SizedBox(width: 8), - Text( - themeService.themeModeDescription, - style: theme.textTheme.bodySmall?.copyWith( - color: theme.colorScheme.onSurface, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ); - }, - ); - } -} - -/// Styles d'affichage pour le ThemeSwitcher -enum ThemeSwitcherStyle { - /// Bouton icône simple qui bascule entre clair/sombre - iconButton, - - /// Menu déroulant avec toutes les options - dropdown, - - /// Boutons segmentés (Material 3) - segmentedButton, - - /// Boutons à bascule - toggleButtons, -} diff --git a/app/linux/CMakeLists.txt b/app/linux/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/app/linux/flutter/CMakeLists.txt b/app/linux/flutter/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus deleted file mode 120000 index 27846f43..00000000 --- a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/battery_plus-6.0.3/ \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/CHANGELOG.md b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/CHANGELOG.md new file mode 100755 index 00000000..cee757d6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/CHANGELOG.md @@ -0,0 +1,372 @@ +## 6.0.3 + + - **CHORE**(battery_plus): Update to package:web to ^1.0.0 ([#3103](https://github.com/fluttercommunity/plus_plugins/pull/3103)). ([cf534eec](https://github.com/fluttercommunity/plus_plugins/commit/cf534eec402b57b70ffe96bf5351afcdfa8c7c7e)) + - **FIX**(battery_plus): Fix type conversion ([#3159](https://github.com/fluttercommunity/plus_plugins/issues/3159)). ([1145af14](https://github.com/fluttercommunity/plus_plugins/commit/1145af14298ecab7d7be57bfa9a32c628b9acdf3)) + - **FIX**(battery_plus): Fix crash when retrieving battery level on desktop Mac. ([#3155](https://github.com/fluttercommunity/plus_plugins/issues/3155)). ([36e7dd16](https://github.com/fluttercommunity/plus_plugins/commit/36e7dd16de3ac43d83eeece7e682b265c93f2fbe)) + - **DOCS**(battery_plus): Update plugin requirements ([#3158](https://github.com/fluttercommunity/plus_plugins/issues/3158)). ([c0353107](https://github.com/fluttercommunity/plus_plugins/commit/c0353107f17e5e32ca33e44742343ccd2c391a0c)) + +## 6.0.2 + + - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) + - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) + +## 6.0.1 + + - **REFACTOR**(battery_plus): Migrate Android example to use the new plugins declaration ([#2772](https://github.com/fluttercommunity/plus_plugins/issues/2772)). ([740a5df2](https://github.com/fluttercommunity/plus_plugins/commit/740a5df21fb84df2b88cea822d53302ce61a6dc2)) + - **FIX**(battery_plus): Fix return value of getBattery to be nullable ([#2745](https://github.com/fluttercommunity/plus_plugins/issues/2745)). ([4d5b950e](https://github.com/fluttercommunity/plus_plugins/commit/4d5b950ed1c74f801f621ef0c07b44f496a7465b)) + +## 6.0.0 + +> Note: This release has breaking changes. + +In this release plugin migrated to package:web, meaning that it now supports WASM! + +Plugin now requires the following: +- Flutter >=3.19.0 +- Dart >=3.3.0 +- compileSDK 34 for Android part +- Java 17 for Android part +- Gradle 8.4 for Android part + +- **BREAKING** **FEAT**(battery_plus): Migrate to package:web ([#2720](https://github.com/fluttercommunity/plus_plugins/issues/2720)). ([21ccfa45](https://github.com/fluttercommunity/plus_plugins/commit/21ccfa459fcfb0609da46299fed6e10c9e77332b)) +- **BREAKING** **BUILD**(battery_plus): Target Java 17 on Android ([#2727](https://github.com/fluttercommunity/plus_plugins/issues/2727)). ([ca2c35ab](https://github.com/fluttercommunity/plus_plugins/commit/ca2c35abc464b26e741ace6e53e319dfa674b630)) +- **BREAKING** **BUILD**(battery_plus): Update to target and compile SDK 34 ([#2702](https://github.com/fluttercommunity/plus_plugins/pull/2702)). ([fc59745](https://github.com/fluttercommunity/plus_plugins/commit/fc59745d0a8650cc32f6e4d949887c4cdbffe547)) +- **BREAKING** **REFACTOR**(battery_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2592](https://github.com/fluttercommunity/plus_plugins/issues/2592)). ([fe07964b](https://github.com/fluttercommunity/plus_plugins/commit/fe07964b03997db73f22f3c30b7d09ea2c0adc93)) + - **FIX**(battery_plus): Add iOS Privacy Info ([#2580](https://github.com/fluttercommunity/plus_plugins/issues/2580)). ([9f36a001](https://github.com/fluttercommunity/plus_plugins/commit/9f36a0018daa08e3f3ebb59cebcd4149fae7c4bc)) + +## 5.0.3 + + - **FIX**(battery_plus): battery state always unknown on iOS ([#2481](https://github.com/fluttercommunity/plus_plugins/issues/2481)). ([ea892fb9](https://github.com/fluttercommunity/plus_plugins/commit/ea892fb96d06dcd685fa7953a468c377cc133ecc)) + +## 5.0.2 + + - **FIX**(battery_plus): Return correct state enum value on Android for not charging state ([#2451](https://github.com/fluttercommunity/plus_plugins/issues/2451)). ([68ddda39](https://github.com/fluttercommunity/plus_plugins/commit/68ddda39f0fa8e7ac950c13721403d49d0d97a65)) + +## 5.0.1 + +> Note: This release has breaking changes. There is a new state for battery available on Android, MacOS and Linux platforms. +> Also, MacOS implementation was updated to provide more accurate battery status. Be sure to test if it affects your MacOS app. + + - **BREAKING** **FIX**(battery_plus): Implement not_charging battery state ([#2275](https://github.com/fluttercommunity/plus_plugins/issues/2275)). ([6595e035](https://github.com/fluttercommunity/plus_plugins/commit/6595e035fd113b4a75651c9d471cc098d5798de3)) + - **BREAKING** **FEAT**(battery_plus): Introduce connected_not_charging state on MacOS ([#2399](https://github.com/fluttercommunity/plus_plugins/issues/2399)). ([78f44bf4](https://github.com/fluttercommunity/plus_plugins/commit/78f44bf41a7e8349240bacae2dd70598ba22e97a)) + - **BREAKING** **FEAT**(battery_plus): Introduce not_charging state on Linux ([#2400](https://github.com/fluttercommunity/plus_plugins/issues/2400)). ([42ef02bd](https://github.com/fluttercommunity/plus_plugins/commit/42ef02bd6de219fef1b2d9db2eebe9775a6ac751)) + - **DOCS**(battery_plus): Improve documentation on battery states ([#2402](https://github.com/fluttercommunity/plus_plugins/issues/2402)). ([baeb886f](https://github.com/fluttercommunity/plus_plugins/commit/baeb886fcc587f72662ce177ab4922496bb1db46)) + - **BREAKING** **FIX**(battery_plus): Bump iOS min target to 12 and update example app ([#2401](https://github.com/fluttercommunity/plus_plugins/issues/2401)). ([25ef7928](https://github.com/fluttercommunity/plus_plugins/commit/25ef7928cd57ca17d6107ed839711ea166d451a6)) + +## 5.0.0 + +This release was retracted due to due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). + +## 4.1.0 + +> Info: This release is a replacement for release 5.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. + + - **FIX**(battery_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2257](https://github.com/fluttercommunity/plus_plugins/issues/2257)). ([f5244e36](https://github.com/fluttercommunity/plus_plugins/commit/f5244e368c74d8b6e7bdd0062a4a2250dcabe540)) + - **FIX**(battery_plus): Revert bump of compileSDK to 34 ([#2228](https://github.com/fluttercommunity/plus_plugins/issues/2228)). ([e834f582](https://github.com/fluttercommunity/plus_plugins/commit/e834f582b85d5fb5a18aefc49b11b039ae600c78)) + - **FEAT**(battery_plus): Remove deprecated VALID_ARCHS iOS property ([#2025](https://github.com/fluttercommunity/plus_plugins/issues/2025)). ([09318317](https://github.com/fluttercommunity/plus_plugins/commit/0931831758dfc829e5649d880a616840a9b1d21f)) + +## 4.0.2 + + - **FIX**(battery_plus): Regenerate iOS and MacOS example apps ([#1873](https://github.com/fluttercommunity/plus_plugins/issues/1873)). ([18deeff3](https://github.com/fluttercommunity/plus_plugins/commit/18deeff3c68f312e2dae0de80273e1991ef97f45)) + - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) + +## 4.0.1 + + - **FIX**(battery_plus): Use ContextCompat on Android to register broadcast receiver ([#1811](https://github.com/fluttercommunity/plus_plugins/issues/1811)). ([b901615c](https://github.com/fluttercommunity/plus_plugins/commit/b901615cdc12d4bc5140ba9713d16f5a85fa6198)) + - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) + - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) + +## 4.0.0 + +> Note: This release has breaking changes. + + - **CHORE**(battery_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 + - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. + - **BREAKING** **CHORE**(battery_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1783). + - **REFACTOR**(battery_plus): Update example app to use Material 3. + - **FIX**(battery_plus): Close StreamController on Web and Linux when done (#1744). + +## 3.0.6 + + - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). + +## 3.0.5 + + - **FIX**(battery_plus): Huawei power save mode check (#1708). + - **FIX**(battery_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1700). + +## 3.0.4 + + - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). + - **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). + +## 3.0.3 + + - **FIX**: broadcast stream (#1479). + - **DOCS**: Updates for READMEs and website pages (#1389). + +## 3.0.2 + + - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). + +## 3.0.1 + + - **FIX**: lint warnings - add missing dependency for tests (#1233). + +## 3.0.0 + +> Note: This release has breaking changes. + + - **BREAKING** **REFACTOR**: platform implementation refactor into a single package (#1169). + +## 2.2.2 + + - **FIX**: batteryState always return unknown on API < 26 (#1120). + +## 2.2.1 + +- Fix: batteryState always return unknown on API < 26 + +## 2.2.0 + +- Android: Migrate to Kotlin +- Android: Bump targetSDK to 33 (Android 13) +- Android: Update dependencies, build config updates +- Update Flutter dependencies + +## 2.1.4+1 + +- Add issue_tracker link. + +## 2.1.4 + +- Update flutter_lints to 2.0.1 +- Update dev dependencies + +## 2.1.3 + +- Update battery_plus_linux dependency +- Set min Flutter version to 1.20.0 for all platforms + +## 2.1.2 + +- Fix embedding issue in example +- (Android) Update Kotlin and Gradle plugin + +## 2.1.1 + +- (Android) Fix null pointer exception in `isInBatterySaveMode()` on Samsung devices with One UI + +## 2.1.0 + +- Add batteryState getter + +## 2.0.2 + +- Update Flutter dependencies + +## 2.0.1 + +- Upgrade Android compile SDK version +- Several code improvements + +## 2.0.0 + +- Remove deprecated method `registerWith` (of Android v1 embedding) + +## 1.2.0 + +- migrate integration_test to flutter sdk + +## 1.1.1 + +- Fix: Add break statements for unknown battery state in Android and iOS implementations + +## 1.1.0 + +- Android, iOS, Windows : add getter for power save mode state + +## 1.0.2 + +- Android: migrate to mavenCentral + +## 1.0.1 + +- Improve documentation + +## 1.0.0 + +- Migrate to null safety + +## 0.10.1 + +- Address pub score + +## 0.10.0 + +- Added "unknown" battery state for batteryless systems. + +## 0.9.1 + +- Send initial battery status for Android + +## 0.9.0 + +- Add Linux support (`battery_plus_linux`) +- Add macOS support (`battery_plus_macos`) +- Add Windows support (`battery_plus_windows`) +- Rename method channel to avoid conflicts + +## 0.8.0 + +- Transfer to plus-plugins monorepo + +## 0.7.0 + +- Battery Plus supports web. + +## 0.6.0 + +- Implement Battery Plus based on new `BatteryPlatformInterface`. + +## 0.5.4 + +- Transfer package to Flutter Community under new name `batter_plus`. + +## 0.5.3 + +- Update package:e2e to use package:integration_test + +## 0.5.2 + +- Update package:e2e reference to use the local version in the flutter/plugins + repository. + +## 0.4.1 + +- Update lower bound of dart dependency to 2.1.0. + +## 0.3.1+10 + +- Update minimum Flutter version to 1.12.13+hotfix.5 +- Fix CocoaPods podspec lint warnings. + +## 0.3.1+9 + +- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). + +## 0.3.1+8 + +- Make the pedantic dev_dependency explicit. + +## 0.3.1+7 + +- Clean up various Android workarounds no longer needed after framework v1.12. + +## 0.3.1+6 + +- Remove the deprecated `author:` field from pubspec.yaml +- Migrate the plugin to the pubspec platforms manifest. +- Require Flutter SDK 1.10.0 or greater. + +## 0.3.1+5 + +- Fix pedantic linter errors. + +## 0.3.1+4 + +- Update and migrate iOS example project. + +## 0.3.1+3 + +- Remove AndroidX warning. + +## 0.3.1+2 + +- Include lifecycle dependency as a compileOnly one on Android to resolve + potential version conflicts with other transitive libraries. + +## 0.3.1+1 + +- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. + +## 0.3.1 + +- Support the v2 Android embedder. + +## 0.3.0+6 + +- Define clang module for iOS. + +## 0.3.0+5 + +- Fix Gradle version. + +## 0.3.0+4 + +- Update Dart code to conform to current Dart formatter. + +## 0.3.0+3 + +- Fix `batteryLevel` usage example in README + +## 0.3.0+2 + +- Bump the minimum Flutter version to 1.2.0. +- Add template type parameter to `invokeMethod` calls. + +## 0.3.0+1 + +- Log a more detailed warning at build time about the previous AndroidX + migration. + +## 0.3.0 + +- **Breaking change**. Migrate from the deprecated original Android Support + Library to AndroidX. This shouldn't result in any functional changes, but it + requires any Android apps using this plugin to [also + migrate](https://developer.android.com/jetpack/androidx/migrate) if they're + using the original support library. + +## 0.2.3 + +- Updated mockito dependency to 3.0.0 to get Dart 2 support. +- Update test package dependency to 1.3.0, and fixed tests to match. + +## 0.2.2 + +- Updated Gradle tooling to match Android Studio 3.1.2. + +## 0.2.1 + +- Fixed Dart 2 type error. +- Removed use of deprecated parameter in example. + +## 0.2.0 + +- **Breaking change**. Set SDK constraints to match the Flutter beta release. + +## 0.1.1 + +- Fixed warnings from the Dart 2.0 analyzer. +- Simplified and upgraded Android project template to Android SDK 27. +- Updated package description. + +## 0.1.0 + +- **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin + 3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in + order to use this version of the plugin. Instructions can be found + [here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1). + +## 0.0.2 + +- Add FLT prefix to iOS types. + +## 0.0.1+1 + +- Updated README + +## 0.0.1 + +- Initial release diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/LICENSE b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/LICENSE new file mode 100755 index 00000000..7b995420 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/LICENSE @@ -0,0 +1,27 @@ +Copyright 2017 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/README.md new file mode 100755 index 00000000..6dfef1f8 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/README.md @@ -0,0 +1,56 @@ +# battery_plus + +[![pub package](https://img.shields.io/pub/v/battery_plus.svg)](https://pub.dev/packages/battery_plus) +[![pub points](https://img.shields.io/pub/points/battery_plus?color=2E8B57&label=pub%20points)](https://pub.dev/packages/battery_plus/score) +[![battery_plus](https://github.com/fluttercommunity/plus_plugins/actions/workflows/battery_plus.yaml/badge.svg)](https://github.com/fluttercommunity/plus_plugins/actions/workflows/battery_plus.yaml) + +[](https://flutter.dev/docs/development/packages-and-plugins/favorites) + +A Flutter plugin to access various information about the battery of the device the app is running on. + +## Platform Support + +| Android | iOS | MacOS | Web | Linux | Windows | +| :-----: | :-: | :---: | :-: | :---: | :----: | +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | + +## Requirements + +- Flutter >=3.19.0 +- Dart >=3.3.0 <4.0.0 +- iOS >=12.0 +- MacOS >=10.14 +- Android `compileSDK` 34 +- Java 17 +- Android Gradle Plugin >=8.3.0 +- Gradle wrapper >=8.4 + +## Usage + +Add `battery_plus` as a dependency in your pubspec.yaml file. + +### Example + +```dart +// Import package +import 'package:battery_plus/battery_plus.dart'; + +// Instantiate it +var battery = Battery(); + +// Access current battery level +print(await battery.batteryLevel); + +// Be informed when the state (full, charging, discharging) changes +battery.onBatteryStateChanged.listen((BatteryState state) { + // Do something with new state +}); + +// Check if device in battery save mode +// Currently available on Android, iOS and Windows platforms only +print(await battery.isInBatterySaveMode); +``` + +## Learn more + +- [API Documentation](https://pub.dev/documentation/battery_plus/latest/battery_plus/battery_plus-library.html) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/build.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/build.gradle new file mode 100755 index 00000000..c7c0c92c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/build.gradle @@ -0,0 +1,53 @@ +group 'dev.fluttercommunity.plus.battery' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.7.22' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.3.1' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdk 34 + + namespace 'dev.fluttercommunity.plus.battery' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = 17 + } + + defaultConfig { + minSdk 19 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + lintOptions { + disable 'InvalidPackage' + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation "androidx.core:core-ktx:1.13.1" +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle.properties new file mode 100755 index 00000000..8bd86f68 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle/wrapper/gradle-wrapper.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..fce403e4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/settings.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/settings.gradle new file mode 100755 index 00000000..ca0ecf2b --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'battery_plus' diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/AndroidManifest.xml new file mode 100755 index 00000000..da40a4e7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt new file mode 100755 index 00000000..f7618902 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt @@ -0,0 +1,219 @@ +package dev.fluttercommunity.plus.battery + +import android.annotation.SuppressLint +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.plugin.common.EventChannel +import io.flutter.embedding.engine.plugins.FlutterPlugin +import android.content.Context +import android.content.BroadcastReceiver +import io.flutter.plugin.common.MethodChannel +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding +import io.flutter.plugin.common.MethodCall +import android.os.Build.VERSION_CODES +import io.flutter.plugin.common.EventChannel.EventSink +import android.content.IntentFilter +import android.content.Intent +import android.os.BatteryManager +import android.os.Build.VERSION +import android.content.ContextWrapper +import android.os.Build +import java.util.Locale +import android.os.PowerManager +import android.provider.Settings +import androidx.annotation.RequiresApi +import androidx.core.content.ContextCompat +import androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED + + +/** BatteryPlusPlugin */ +class BatteryPlusPlugin : MethodCallHandler, EventChannel.StreamHandler, FlutterPlugin { + private var applicationContext: Context? = null + private var chargingStateChangeReceiver: BroadcastReceiver? = null + private var methodChannel: MethodChannel? = null + private var eventChannel: EventChannel? = null + + override fun onAttachedToEngine(binding: FlutterPluginBinding) { + this.applicationContext = binding.applicationContext + methodChannel = MethodChannel(binding.binaryMessenger, "dev.fluttercommunity.plus/battery") + eventChannel = EventChannel(binding.binaryMessenger, "dev.fluttercommunity.plus/charging") + eventChannel!!.setStreamHandler(this) + methodChannel!!.setMethodCallHandler(this) + } + + override fun onDetachedFromEngine(binding: FlutterPluginBinding) { + applicationContext = null + methodChannel!!.setMethodCallHandler(null) + methodChannel = null + eventChannel!!.setStreamHandler(null) + eventChannel = null + } + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + when (call.method) { + "getBatteryLevel" -> { + val currentBatteryLevel = getBatteryLevel() + if (currentBatteryLevel != -1) { + result.success(currentBatteryLevel) + } else { + result.error("UNAVAILABLE", "Battery level not available.", null) + } + } + + "getBatteryState" -> { + val currentBatteryStatus = getBatteryStatus() + if (currentBatteryStatus != null) { + result.success(currentBatteryStatus) + } else { + result.error("UNAVAILABLE", "Charging status not available.", null) + } + } + + "isInBatterySaveMode" -> { + val isInPowerSaveMode = isInPowerSaveMode() + if (isInPowerSaveMode != null) { + result.success(isInPowerSaveMode) + } else { + result.error("UNAVAILABLE", "Battery save mode not available.", null) + } + } + + else -> result.notImplemented() + } + } + + @SuppressLint("WrongConstant") // Error in ContextCompat for RECEIVER_NOT_EXPORTED + override fun onListen(arguments: Any?, events: EventSink) { + chargingStateChangeReceiver = createChargingStateChangeReceiver(events) + applicationContext?.let { + ContextCompat.registerReceiver( + it, chargingStateChangeReceiver, + IntentFilter(Intent.ACTION_BATTERY_CHANGED), RECEIVER_NOT_EXPORTED + ) + } + val status = getBatteryStatus() + publishBatteryStatus(events, status) + } + + override fun onCancel(arguments: Any?) { + applicationContext!!.unregisterReceiver(chargingStateChangeReceiver) + chargingStateChangeReceiver = null + } + + private fun getBatteryStatus(): String? { + val status: Int = if (VERSION.SDK_INT >= VERSION_CODES.O) { + getBatteryProperty(BatteryManager.BATTERY_PROPERTY_STATUS) + } else { + val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + intent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1 + } + return convertBatteryStatus(status) + } + + private fun getBatteryLevel(): Int { + return if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + getBatteryProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) + } else { + val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + val level = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) + val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1) + (level * 100 / scale) + } + } + + private fun isInPowerSaveMode(): Boolean? { + val deviceManufacturer = Build.MANUFACTURER.lowercase(Locale.getDefault()) + + return if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + when (deviceManufacturer) { + "xiaomi" -> isXiaomiPowerSaveModeActive() + "huawei" -> isHuaweiPowerSaveModeActive() + "samsung" -> isSamsungPowerSaveModeActive() + else -> checkPowerServiceSaveMode() + } + } else { + null + } + } + + private fun isSamsungPowerSaveModeActive(): Boolean { + val mode = Settings.System.getString(applicationContext!!.contentResolver, POWER_SAVE_MODE_SAMSUNG_NAME) + return if (mode == null && VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + checkPowerServiceSaveMode() + } else { + mode == POWER_SAVE_MODE_SAMSUNG_VALUE + } + } + + @RequiresApi(VERSION_CODES.LOLLIPOP) + private fun isHuaweiPowerSaveModeActive(): Boolean { + val mode = Settings.System.getInt(applicationContext!!.contentResolver, POWER_SAVE_MODE_HUAWEI_NAME, -1) + return if (mode != -1) { + mode == POWER_SAVE_MODE_HUAWEI_VALUE + } else { + // On Devices like the P30 lite, we always get an -1 result code. + // Stackoverflow issue: https://stackoverflow.com/a/70500770 + checkPowerServiceSaveMode() + } + } + + private fun isXiaomiPowerSaveModeActive(): Boolean? { + val mode = Settings.System.getInt(applicationContext!!.contentResolver, POWER_SAVE_MODE_XIAOMI_NAME, -1) + return if (mode != -1) { + mode == POWER_SAVE_MODE_XIAOMI_VALUE + } else { + null + } + } + + @RequiresApi(api = VERSION_CODES.LOLLIPOP) + private fun checkPowerServiceSaveMode(): Boolean { + val powerManager = + applicationContext!!.getSystemService(Context.POWER_SERVICE) as PowerManager + return powerManager.isPowerSaveMode + } + + @RequiresApi(api = VERSION_CODES.LOLLIPOP) + private fun getBatteryProperty(property: Int): Int { + val batteryManager = applicationContext!!.getSystemService(Context.BATTERY_SERVICE) as BatteryManager + return batteryManager.getIntProperty(property) + } + + private fun createChargingStateChangeReceiver(events: EventSink): BroadcastReceiver { + return object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1) + publishBatteryStatus(events, convertBatteryStatus(status)) + } + } + } + + private fun convertBatteryStatus(status: Int): String? { + return when (status) { + BatteryManager.BATTERY_STATUS_CHARGING -> "charging" + BatteryManager.BATTERY_STATUS_FULL -> "full" + BatteryManager.BATTERY_STATUS_DISCHARGING -> "discharging" + BatteryManager.BATTERY_STATUS_NOT_CHARGING -> "connected_not_charging" + BatteryManager.BATTERY_STATUS_UNKNOWN -> "unknown" + else -> null + } + } + + private fun publishBatteryStatus(events: EventSink, status: String?) { + if (status != null) { + events.success(status) + } else { + events.error("UNAVAILABLE", "Charging status unavailable", null) + } + } + + companion object { + private const val POWER_SAVE_MODE_SAMSUNG_NAME = "psm_switch" + private const val POWER_SAVE_MODE_SAMSUNG_VALUE = "1" + + private const val POWER_SAVE_MODE_XIAOMI_NAME = "POWER_SAVE_MODE_OPEN" + private const val POWER_SAVE_MODE_XIAOMI_VALUE = 1 + + private const val POWER_SAVE_MODE_HUAWEI_NAME = "SmartModeStatus" + private const val POWER_SAVE_MODE_HUAWEI_VALUE = 4 + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/README.md new file mode 100755 index 00000000..9dc0c13e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/README.md @@ -0,0 +1,5 @@ +# battery_plus_example + +Demonstrates how to use the [battery_plus plugin][1] + +[1]: ../ \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/build.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/build.gradle new file mode 100755 index 00000000..52b4b072 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/build.gradle @@ -0,0 +1,67 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + compileSdk 34 + + namespace 'io.flutter.plugins.batteryexample.example' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = 17 + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "io.flutter.plugins.batteryexample.example" + minSdk 21 + targetSdk 34 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + 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.debug + } + } +} + +flutter { + source '../..' +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/debug/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/debug/AndroidManifest.xml new file mode 100755 index 00000000..f094cef4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/AndroidManifest.xml new file mode 100755 index 00000000..dd87ee3a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/kotlin/io/flutter/plugins/batteryexample/example/MainActivity.kt b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/kotlin/io/flutter/plugins/batteryexample/example/MainActivity.kt new file mode 100755 index 00000000..f1c91930 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/kotlin/io/flutter/plugins/batteryexample/example/MainActivity.kt @@ -0,0 +1,5 @@ +package io.flutter.plugins.batteryexample.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/drawable/launch_background.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100755 index 00000000..304732f8 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100755 index 00000000..db77bb4b Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100755 index 00000000..17987b79 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100755 index 00000000..09d43914 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100755 index 00000000..d5f1c8d3 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100755 index 00000000..4d6372ee Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/values/styles.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/values/styles.xml new file mode 100755 index 00000000..1f83a33f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/profile/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/profile/AndroidManifest.xml new file mode 100755 index 00000000..f094cef4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/build.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/build.gradle new file mode 100755 index 00000000..bc157bd1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle.properties new file mode 100755 index 00000000..d9cf55df --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..825c34f1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Oct 05 14:03:03 CEST 2021 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/settings.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/settings.gradle new file mode 100755 index 00000000..fa3b4d08 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/settings.gradle @@ -0,0 +1,25 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.3.1" apply false + id "org.jetbrains.kotlin.android" version "1.9.23" apply false +} + +include ":app" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/integration_test/battery_plus_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/integration_test/battery_plus_test.dart new file mode 100755 index 00000000..41a500e7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/integration_test/battery_plus_test.dart @@ -0,0 +1,40 @@ +// Copyright 2020, the Chromium authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +import 'dart:io'; + +import 'package:battery_plus/battery_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + final bool batteryLevelIsImplemented = + Platform.isAndroid || Platform.isMacOS || Platform.isLinux; + final bool batteryStateIsImplemented = Platform.isAndroid || + Platform.isIOS || + Platform.isMacOS || + Platform.isWindows || + Platform.isLinux; + final bool isInBatterySaveModeIsImplemented = + Platform.isAndroid || Platform.isIOS || Platform.isWindows; + + /// Throws [PlatformException] on iOS simulator and Windows. + /// Run on Android only. + testWidgets('Can get battery level', (WidgetTester tester) async { + final batteryLevel = await Battery().batteryLevel; + expect(batteryLevel, isNotNull); + }, skip: !batteryLevelIsImplemented); + + testWidgets('Can get battery state', (WidgetTester tester) async { + final batteryState = await Battery().batteryState; + expect(batteryState, isNotNull); + }, skip: !batteryStateIsImplemented); + + testWidgets('Can get if device is in battery save mode', + (WidgetTester tester) async { + final isInBatterySaveMode = await Battery().isInBatterySaveMode; + expect(isInBatterySaveMode, false); + }, skip: !isInBatterySaveModeIsImplemented); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/AppFrameworkInfo.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100755 index 00000000..9625e105 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Debug.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Debug.xcconfig new file mode 100755 index 00000000..ec97fc6f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Release.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Release.xcconfig new file mode 100755 index 00000000..c4855bfe --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.pbxproj b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..f983bf7a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,721 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97AE7F1E32AA538C368FCC3F /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D432E8EDF62A8247198B1CAB /* Pods_RunnerTests.framework */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + D698218E8DD3B8EB846F3847 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B57435E320EDA8EA441D43AF /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4CAB07678B2F77AE275A0BEC /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 50957247B576084F0771E61F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 650E23DC8A7DFC99D7539C89 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 75FBB03C676F0D043B4369C7 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 7AF090DBA22B5ED51CC286D2 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B57435E320EDA8EA441D43AF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D432E8EDF62A8247198B1CAB /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F41590C41B15A335C8248CA6 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D698218E8DD3B8EB846F3847 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FC2D413132B4BF4DF093FCCB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 97AE7F1E32AA538C368FCC3F /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 5BA506C21DC982245BC4307C /* Pods */ = { + isa = PBXGroup; + children = ( + 650E23DC8A7DFC99D7539C89 /* Pods-Runner.debug.xcconfig */, + 50957247B576084F0771E61F /* Pods-Runner.release.xcconfig */, + F41590C41B15A335C8248CA6 /* Pods-Runner.profile.xcconfig */, + 75FBB03C676F0D043B4369C7 /* Pods-RunnerTests.debug.xcconfig */, + 7AF090DBA22B5ED51CC286D2 /* Pods-RunnerTests.release.xcconfig */, + 4CAB07678B2F77AE275A0BEC /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 5FC27932B351D2B369512AAA /* Frameworks */ = { + isa = PBXGroup; + children = ( + B57435E320EDA8EA441D43AF /* Pods_Runner.framework */, + D432E8EDF62A8247198B1CAB /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + 5BA506C21DC982245BC4307C /* Pods */, + 5FC27932B351D2B369512AAA /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 2475DCCE7D4FDE42E0DECD43 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + FC2D413132B4BF4DF093FCCB /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + DEE2275EA4B4ABAF40CF9EB0 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 3785BB9002D6BDCD15832A60 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2475DCCE7D4FDE42E0DECD43 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3785BB9002D6BDCD15832A60 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + DEE2275EA4B4ABAF40CF9EB0 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 75FBB03C676F0D043B4369C7 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AF090DBA22B5ED51CC286D2 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4CAB07678B2F77AE275A0BEC /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..919434a6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..e42adcb3 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/AppDelegate.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/AppDelegate.swift new file mode 100755 index 00000000..70693e4a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..d36b1fab --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100755 index 00000000..dc9ada47 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100755 index 00000000..7353c41e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100755 index 00000000..6ed2d933 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100755 index 00000000..4cd7b009 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100755 index 00000000..fe730945 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100755 index 00000000..321773cd Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100755 index 00000000..502f463a Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100755 index 00000000..e9f5fea2 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100755 index 00000000..84ac32ae Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100755 index 00000000..8953cba0 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100755 index 00000000..0467bf12 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100755 index 00000000..0bedcf2f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100755 index 00000000..89c2725b --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 00000000..f2e259c7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/Main.storyboard b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100755 index 00000000..f3c28516 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Info.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Info.plist new file mode 100755 index 00000000..d5a7c08f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Battery Plus Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + battery_plus_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Runner-Bridging-Header.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Runner-Bridging-Header.h new file mode 100755 index 00000000..308a2a56 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/RunnerTests/RunnerTests.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..86a7c3b1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/lib/main.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/lib/main.dart new file mode 100755 index 00000000..a6f34822 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/lib/main.dart @@ -0,0 +1,145 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:battery_plus/battery_plus.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + useMaterial3: true, + colorSchemeSeed: const Color(0x9f4376f8), + ), + home: const MyHomePage(), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key}); + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + final Battery _battery = Battery(); + + BatteryState? _batteryState; + StreamSubscription? _batteryStateSubscription; + + @override + void initState() { + super.initState(); + _battery.batteryState.then(_updateBatteryState); + _batteryStateSubscription = + _battery.onBatteryStateChanged.listen(_updateBatteryState); + } + + void _updateBatteryState(BatteryState state) { + if (_batteryState == state) return; + setState(() { + _batteryState = state; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Battery plus example app'), + elevation: 4, + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Current battery state:', + style: TextStyle(fontSize: 24), + ), + const SizedBox(height: 8), + Text( + '${_batteryState?.name}', + style: const TextStyle(fontSize: 24), + ), + const SizedBox(height: 24), + ElevatedButton( + onPressed: () { + _battery.batteryLevel.then( + (batteryLevel) { + showDialog( + context: context, + builder: (_) => AlertDialog( + content: Text('Battery: $batteryLevel%'), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text('OK'), + ) + ], + ), + ); + }, + ); + }, + child: const Text('Get battery level'), + ), + const SizedBox(height: 24), + ElevatedButton( + onPressed: () { + _battery.isInBatterySaveMode.then( + (isInPowerSaveMode) { + showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text( + 'Is in Battery Save mode?', + style: TextStyle(fontSize: 20), + ), + content: Text( + "$isInPowerSaveMode", + style: const TextStyle(fontSize: 18), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text('Close'), + ) + ], + ), + ); + }, + ); + }, + child: const Text('Is in Battery Save mode?'), + ) + ], + ), + ), + ); + } + + @override + void dispose() { + super.dispose(); + if (_batteryStateSubscription != null) { + _batteryStateSubscription!.cancel(); + } + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/CMakeLists.txt new file mode 100755 index 00000000..386893d7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "io.flutter.plugins.batteryexample.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..5b465c7e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/main.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/main.cc new file mode 100755 index 00000000..8bc15615 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/main.cc @@ -0,0 +1,11 @@ +#include "my_application.h" + +int main(int argc, char **argv) { + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); + + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.cc new file mode 100755 index 00000000..cef2f771 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.cc @@ -0,0 +1,45 @@ +#include "my_application.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication *application) { + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +static void my_application_class_init(MyApplicationClass *klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; +} + +static void my_application_init(MyApplication *self) {} + +MyApplication *my_application_new() { + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.h new file mode 100755 index 00000000..3258a73c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication *my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Debug.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100755 index 00000000..4b81f9b2 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Release.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100755 index 00000000..5caa9d15 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.pbxproj b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..9e9505e8 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,791 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 093D643C82D4B7EE630E0DE2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB44BF446D4E3EDCD5B77BA3 /* Pods_Runner.framework */; }; + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 90893944B3704A3D4ED269F2 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6AE51C6475BCF9D909943E1 /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* battery_plus_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = battery_plus_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 3BD291780B1536D56E3D8614 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 49893D8393C2F92741388488 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 58313ABA94CF9296393DDC88 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 58950022FA3EF51275C04A8A /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + A6AE51C6475BCF9D909943E1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B872A381CB0689F35D462D2B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + CB44BF446D4E3EDCD5B77BA3 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E95D25412347C218A8EAE4BA /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 90893944B3704A3D4ED269F2 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 093D643C82D4B7EE630E0DE2 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 9F06F6A0F47185C443DA9499 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* battery_plus_example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + 9F06F6A0F47185C443DA9499 /* Pods */ = { + isa = PBXGroup; + children = ( + 49893D8393C2F92741388488 /* Pods-Runner.debug.xcconfig */, + 3BD291780B1536D56E3D8614 /* Pods-Runner.release.xcconfig */, + B872A381CB0689F35D462D2B /* Pods-Runner.profile.xcconfig */, + E95D25412347C218A8EAE4BA /* Pods-RunnerTests.debug.xcconfig */, + 58313ABA94CF9296393DDC88 /* Pods-RunnerTests.release.xcconfig */, + 58950022FA3EF51275C04A8A /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CB44BF446D4E3EDCD5B77BA3 /* Pods_Runner.framework */, + A6AE51C6475BCF9D909943E1 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + F2FDA1BE1872CC09A966504C /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 4C38364606CE0024B21D00BA /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 86E7C6C5AB4A292BD51729FA /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* battery_plus_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 4C38364606CE0024B21D00BA /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 86E7C6C5AB4A292BD51729FA /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F2FDA1BE1872CC09A966504C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E95D25412347C218A8EAE4BA /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/battery_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/battery_plus_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 58313ABA94CF9296393DDC88 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/battery_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/battery_plus_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 58950022FA3EF51275C04A8A /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/battery_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/battery_plus_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..15041ed5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/AppDelegate.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/AppDelegate.swift new file mode 100755 index 00000000..d53ef643 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..a2ec33f1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "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" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100755 index 00000000..82b6f9d9 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100755 index 00000000..13b35eba Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100755 index 00000000..0a3f5fa4 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100755 index 00000000..bdb57226 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100755 index 00000000..f083318e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100755 index 00000000..326c0e72 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100755 index 00000000..2f1632cf Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Base.lproj/MainMenu.xib b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100755 index 00000000..80e867a4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/AppInfo.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100755 index 00000000..2f815b1f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = battery_plus_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlus.example + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 io.flutter.plugins. All rights reserved. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Debug.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Debug.xcconfig new file mode 100755 index 00000000..36b0fd94 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Release.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Release.xcconfig new file mode 100755 index 00000000..dff4f495 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Warnings.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100755 index 00000000..42bcbf47 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/DebugProfile.entitlements b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/DebugProfile.entitlements new file mode 100755 index 00000000..dddb8a30 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Info.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Info.plist new file mode 100755 index 00000000..4789daa6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/MainFlutterWindow.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/MainFlutterWindow.swift new file mode 100755 index 00000000..3cc05eb2 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Release.entitlements b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Release.entitlements new file mode 100755 index 00000000..852fa1a4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/RunnerTests/RunnerTests.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..5418c9f5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/pubspec.yaml new file mode 100755 index 00000000..bcdf8703 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/pubspec.yaml @@ -0,0 +1,23 @@ +name: battery_plus_example +description: Demonstrates how to use the battery_plus plugin. + +environment: + sdk: '>=3.3.0 <4.0.0' + flutter: '>=3.19.0' + +dependencies: + flutter: + sdk: flutter + battery_plus: ^6.0.3 + +dev_dependencies: + flutter_driver: + sdk: flutter + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + flutter_lints: ^4.0.0 + +flutter: + uses-material-design: true diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/test/widget_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/test/widget_test.dart new file mode 100755 index 00000000..0ca91e79 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/test/widget_test.dart @@ -0,0 +1,19 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:battery_plus_example/main.dart'; + +void main() { + testWidgets('Initial battery value smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + expect(find.text('null'), findsOneWidget); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/favicon.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/favicon.png new file mode 100755 index 00000000..8aaa46ac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/favicon.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-192.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-192.png new file mode 100755 index 00000000..b749bfef Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-192.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-512.png b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-512.png new file mode 100755 index 00000000..88cfd48d Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-512.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/index.html b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/index.html new file mode 100755 index 00000000..a0c14606 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/manifest.json b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/manifest.json new file mode 100755 index 00000000..8c012917 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/CMakeLists.txt new file mode 100755 index 00000000..abf90408 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.15) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..744f08a9 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..977e38b5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/Runner.rc b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/Runner.rc new file mode 100755 index 00000000..9b0221d3 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "io.flutter.plugins.batteryexample" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2020 io.flutter.plugins.batteryexample. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..0f0105d9 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.cpp @@ -0,0 +1,64 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opporutunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..69234d4f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.h @@ -0,0 +1,39 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "run_loop.h" +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { +public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + virtual ~FlutterWindow(); + +protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + +private: + // The run loop driving events for this window. + RunLoop *run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/main.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/main.cpp new file mode 100755 index 00000000..fc17fec6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/main.cpp @@ -0,0 +1,36 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resource.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resources/app_icon.ico b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resources/app_icon.ico differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.cpp new file mode 100755 index 00000000..31b89f62 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.cpp @@ -0,0 +1,66 @@ +#include "run_loop.h" + +#include + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto instance : flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.h new file mode 100755 index 00000000..7fe1aacc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.h @@ -0,0 +1,38 @@ +#ifndef RUNNER_RUN_LOOP_H_ +#define RUNNER_RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { +public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const &) = delete; + RunLoop &operator=(RunLoop const &) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + +private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUNNER_RUN_LOOP_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/runner.exe.manifest b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.cpp new file mode 100755 index 00000000..37501e5d --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.cpp @@ -0,0 +1,22 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.h new file mode 100755 index 00000000..7021e6d0 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.h @@ -0,0 +1,8 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..9669d7fc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.cpp @@ -0,0 +1,236 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { +public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + +private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar *instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; + +const wchar_t *WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size) { + Destroy(); + + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window *that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.h new file mode 100755 index 00000000..7b518125 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.h @@ -0,0 +1,95 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { +public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.h new file mode 100755 index 00000000..5c205f90 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.h @@ -0,0 +1,8 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface FPPBatteryPlusPlugin : NSObject +@end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.m b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.m new file mode 100755 index 00000000..3f755e4b --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.m @@ -0,0 +1,121 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "FPPBatteryPlusPlugin.h" + +@interface FPPBatteryPlusPlugin () +@end + +@implementation FPPBatteryPlusPlugin { + FlutterEventSink _eventSink; +} + ++ (void)registerWithRegistrar:(NSObject *)registrar { + FPPBatteryPlusPlugin *instance = [[FPPBatteryPlusPlugin alloc] init]; + + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/battery" + binaryMessenger:[registrar messenger]]; + + [registrar addMethodCallDelegate:instance channel:channel]; + FlutterEventChannel *chargingChannel = [FlutterEventChannel + eventChannelWithName:@"dev.fluttercommunity.plus/charging" + binaryMessenger:[registrar messenger]]; + [chargingChannel setStreamHandler:instance]; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call + result:(FlutterResult)result { + if ([@"getBatteryLevel" isEqualToString:call.method]) { + int batteryLevel = [self getBatteryLevel]; + if (batteryLevel == -1) { + result([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Battery info unavailable" + details:nil]); + } else { + result(@(batteryLevel)); + } + } else if ([@"getBatteryState" isEqualToString:call.method]) { + NSString *state = [self getBatteryState]; + if (state) { + result(state); + } else { + result([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Charging status unavailable" + details:nil]); + } + } else if ([@"isInBatterySaveMode" isEqualToString:call.method]) { + result(@([[NSProcessInfo processInfo] isLowPowerModeEnabled])); + } else { + result(FlutterMethodNotImplemented); + } +} + +- (void)onBatteryStateDidChange:(NSNotification *)notification { + [self sendBatteryStateEvent]; +} + +- (void)sendBatteryStateEvent { + if (!_eventSink) + return; + NSString *state = [self getBatteryState]; + if (state) { + _eventSink(state); + } else { + _eventSink([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Charging status unavailable" + details:nil]); + } +} + +- (NSString *)getBatteryState { + UIDevice *device = UIDevice.currentDevice; + device.batteryMonitoringEnabled = YES; + UIDeviceBatteryState state = [device batteryState]; + switch (state) { + case UIDeviceBatteryStateUnknown: + return @"unknown"; + case UIDeviceBatteryStateFull: + return @"full"; + case UIDeviceBatteryStateCharging: + return @"charging"; + case UIDeviceBatteryStateUnplugged: + return @"discharging"; + default: + return nil; + } +} + +- (int)getBatteryLevel { + UIDevice *device = UIDevice.currentDevice; + device.batteryMonitoringEnabled = YES; + if (device.batteryState == UIDeviceBatteryStateUnknown) { + return -1; + } else { + return ((int)(device.batteryLevel * 100)); + } +} + +#pragma mark FlutterStreamHandler impl + +- (FlutterError *)onListenWithArguments:(id)arguments + eventSink:(FlutterEventSink)eventSink { + _eventSink = eventSink; + [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES]; + [self sendBatteryStateEvent]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onBatteryStateDidChange:) + name:UIDeviceBatteryStateDidChangeNotification + object:nil]; + return nil; +} + +- (FlutterError *)onCancelWithArguments:(id)arguments { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + _eventSink = nil; + return nil; +} + +@end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/PrivacyInfo.xcprivacy b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/PrivacyInfo.xcprivacy new file mode 100755 index 00000000..a34b7e2e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/battery_plus.podspec b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/battery_plus.podspec new file mode 100755 index 00000000..39c05510 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/battery_plus.podspec @@ -0,0 +1,24 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'battery_plus' + s.version = '1.0.0' + s.summary = 'Flutter plugin for accessing information about the battery_plus.' + s.description = <<-DESC +A Flutter plugin to access various information about the battery of the device the app is running on. +Downloaded by pub (not CocoaPods). + DESC + s.homepage = 'https://plus.fluttercommunity.dev/' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Community Team' => 'authors@fluttercommunity.dev' } + s.source = { :http => 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus' } + s.documentation_url = 'https://pub.dev/packages/battery_plus' + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + + s.platform = :ios, '12.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.resource_bundles = {'batery_plus_privacy' => ['PrivacyInfo.xcprivacy']} +end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/battery_plus.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/battery_plus.dart new file mode 100755 index 00000000..0ffaff6a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/battery_plus.dart @@ -0,0 +1,56 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; + +export 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart' + show BatteryState; + +export 'src/battery_plus_linux.dart'; + +/// API for accessing information about the battery of the device the Flutter app is running on. +class Battery { + /// Constructs a singleton instance of [Battery]. + /// + /// [Battery] is designed to work as a singleton. + // When a second instance is created, the first instance will not be able to listen to the + // EventChannel because it is overridden. Forcing the class to be a singleton class can prevent + // misuse of creating a second instance from a programmer. + factory Battery() { + _singleton ??= Battery._(); + return _singleton!; + } + + Battery._(); + + static Battery? _singleton; + + static BatteryPlatform get _platform { + return BatteryPlatform.instance; + } + + /// get battery level + Future get batteryLevel { + return _platform.batteryLevel; + } + + /// check if device is on battery save mode + /// + /// Currently only implemented on Android, iOS and Windows. + Future get isInBatterySaveMode { + return _platform.isInBatterySaveMode; + } + + /// Get battery state + Future get batteryState { + return _platform.batteryState; + } + + /// Fires whenever the battery state changes. + Stream get onBatteryStateChanged { + return _platform.onBatteryStateChanged; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_linux.dart new file mode 100755 index 00000000..89ab9b77 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_linux.dart @@ -0,0 +1,98 @@ +import 'dart:async'; + +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; +import 'package:meta/meta.dart'; +import 'package:upower/upower.dart'; + +extension _ToBatteryState on UPowerDeviceState { + BatteryState toBatteryState() { + switch (this) { + case UPowerDeviceState.charging: + return BatteryState.charging; + + case UPowerDeviceState.discharging: + case UPowerDeviceState.pendingDischarge: + return BatteryState.discharging; + + case UPowerDeviceState.fullyCharged: + return BatteryState.full; + + case UPowerDeviceState.pendingCharge: + return BatteryState.connectedNotCharging; + + default: + return BatteryState.unknown; + } + } +} + +/// +@visibleForTesting +typedef UPowerClientFactory = UPowerClient Function(); + +/// The Linux implementation of BatteryPlatform. +class BatteryPlusLinuxPlugin extends BatteryPlatform { + /// Register this dart class as the platform implementation for linux + static void registerWith() { + BatteryPlatform.instance = BatteryPlusLinuxPlugin(); + } + + /// Returns the current battery level in percent. + @override + Future get batteryLevel { + final client = createClient(); + return client + .connect() + .then((_) => client.displayDevice.percentage.round()) + .whenComplete(() => client.close()); + } + + /// Returns the current battery state. + @override + Future get batteryState { + final client = createClient(); + return client + .connect() + .then((_) => client.displayDevice.state.toBatteryState()) + .whenComplete(() => client.close); + } + + /// Fires whenever the battery state changes. + @override + Stream get onBatteryStateChanged { + _stateController ??= StreamController.broadcast( + onListen: _startListenState, + onCancel: _stopListenState, + ); + return _stateController!.stream.asBroadcastStream(); + } + + UPowerClient? _stateClient; + StreamController? _stateController; + + @visibleForTesting + // ignore: public_member_api_docs, prefer_function_declarations_over_variables + UPowerClientFactory createClient = () => UPowerClient(); + + void _addState(UPowerDeviceState value) { + _stateController!.add(value.toBatteryState()); + } + + Future _startListenState() async { + _stateClient ??= createClient(); + await _stateClient! + .connect() + .then((_) => _addState(_stateClient!.displayDevice.state)); + _stateClient!.displayDevice.propertiesChanged.listen((properties) { + if (properties.contains('State')) { + _addState(_stateClient!.displayDevice.state); + } + }); + } + + void _stopListenState() { + _stateController?.close(); + _stateClient?.close(); + _stateClient = null; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_web.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_web.dart new file mode 100755 index 00000000..f179ad28 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_web.dart @@ -0,0 +1,107 @@ +import 'dart:async'; +import 'dart:js_interop'; + +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:web/web.dart'; + +/// The web implementation of the BatteryPlatform of the Battery plugin. +/// +/// The Battery Status API is not supported by Firefox and Safari. +/// Therefore, when using this plugin, recommend that test not only in Chrome but also in Firefox and Safari. +/// In some environments, accessing this plugin from Firefox or Safari will cause unexpected exception. +/// If an unexpected Exception occurs, try-catch at the point where the method is being called. +class BatteryPlusWebPlugin extends BatteryPlatform { + /// Constructs a BatteryPlusPlugin. + BatteryPlusWebPlugin(); + + /// Return [BatteryManager] if the BatteryManager API is supported by the User Agent. + Future _getBatteryManager() async { + try { + return await window.navigator.getBattery().toDart; + } on NoSuchMethodError catch (_) { + // BatteryManager API is not supported this User Agent. + return null; + } on Object catch (_) { + // Unexpected exception occurred. + return null; + } + } + + /// Factory method that initializes the Battery plugin platform with an instance + /// of the plugin for the web. + static void registerWith(Registrar registrar) { + BatteryPlatform.instance = BatteryPlusWebPlugin(); + } + + /// Returns the current battery level in percent. + @override + Future get batteryLevel async { + final batteryManager = await _getBatteryManager(); + if (batteryManager == null) { + return 0; + } + + // level is a number representing the system's battery charge level scaled to a value between 0.0 and 1.0 + final level = batteryManager.level; + return (level * 100).toInt(); + } + + /// Returns the current battery state. + @override + Future get batteryState async { + final batteryManager = await _getBatteryManager(); + if (batteryManager == null) { + return BatteryState.unknown; + } + + return _checkBatteryChargingState(batteryManager.charging); + } + + StreamController? _batteryChangeStreamController; + Stream? _batteryChange; + + /// Returns a Stream of BatteryState changes. + @override + Stream get onBatteryStateChanged async* { + final batteryManager = await _getBatteryManager(); + if (batteryManager == null) { + yield BatteryState.unknown; + return; + } + + if (_batteryChange != null) { + yield* _batteryChange!; + return; + } + + _batteryChangeStreamController = StreamController(); + _batteryChangeStreamController?.add( + _checkBatteryChargingState(batteryManager.charging), + ); + + batteryManager.onchargingchange = (Event _) { + _batteryChangeStreamController?.add( + _checkBatteryChargingState(batteryManager.charging), + ); + }.toJS; + + _batteryChangeStreamController?.onCancel = () { + _batteryChangeStreamController?.close(); + + _batteryChangeStreamController = null; + _batteryChange = null; + }; + + _batteryChange = _batteryChangeStreamController!.stream.asBroadcastStream(); + yield* _batteryChange!; + } + + BatteryState _checkBatteryChargingState(bool charging) { + if (charging) { + return BatteryState.charging; + } else { + return BatteryState.discharging; + } + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusChargingHandler.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusChargingHandler.swift new file mode 100755 index 00000000..902fc75b --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusChargingHandler.swift @@ -0,0 +1,87 @@ +import Foundation +import FlutterMacOS + +class BatteryPlusChargingHandler: NSObject, FlutterStreamHandler { + + private var context: Int = 0 + + private var source: CFRunLoopSource? + private var runLoop: CFRunLoop? + private var eventSink: FlutterEventSink? + + func onListen(withArguments arguments: Any?, eventSink event: @escaping FlutterEventSink) -> FlutterError? { + self.eventSink = event + start() + return nil + } + + func onCancel(withArguments arguments: Any?) -> FlutterError? { + stop() + self.eventSink = nil + return nil + } + + func start() { + // If there is an added loop, we remove it before adding a new one. + stop() + + // Gets the initial battery status + let initialStatus = getBatteryStatus() + if let sink = self.eventSink { + sink(initialStatus) + } + + // Registers a run loop which is notified when the battery status changes + let context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()) + source = IOPSNotificationCreateRunLoopSource({ (context) in + let _self = Unmanaged.fromOpaque(UnsafeRawPointer(context!)).takeUnretainedValue() + let status = _self.getBatteryStatus() + print(status) + if let sink = _self.eventSink { + sink(status) + } + }, context).takeUnretainedValue() + + // Adds loop to source + runLoop = RunLoop.current.getCFRunLoop() + CFRunLoopAddSource(runLoop, source, .defaultMode) + } + + func stop() { + guard let runLoop = runLoop, let source = source else { + return + } + CFRunLoopRemoveSource(runLoop, source, .defaultMode) + } + + func getBatteryStatus()-> String { + let powerSourceSnapshot = IOPSCopyPowerSourcesInfo().takeRetainedValue() + let sources = IOPSCopyPowerSourcesList(powerSourceSnapshot).takeRetainedValue() as [CFTypeRef] + + // When no sources available it is highly likely a desktop, thus, connected_not_charging. + if sources.isEmpty { + return "connected_not_charging" + } + + let description = IOPSGetPowerSourceDescription(powerSourceSnapshot, sources[0]).takeUnretainedValue() as! [String: AnyObject] + + if let isFullyCharged = description[kIOPSIsChargedKey] as? Bool { + if isFullyCharged { + return "full" + } + } + + let isConnected = (description[kIOPSPowerSourceStateKey] as? String) + + if let isCharging = (description[kIOPSIsChargingKey] as? Bool) { + if isCharging { + return "charging" + } else if isConnected == kIOPSACPowerValue { + return "connected_not_charging" + } else { + return "discharging" + } + } + return "UNAVAILABLE" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusMacosPlugin.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusMacosPlugin.swift new file mode 100755 index 00000000..246336c0 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusMacosPlugin.swift @@ -0,0 +1,65 @@ +import Cocoa +import FlutterMacOS +import IOKit.ps + +public class BatteryPlusMacosPlugin: NSObject, FlutterPlugin { + private var chargingHandler: BatteryPlusChargingHandler + + init(chargingHandler: BatteryPlusChargingHandler) { + self.chargingHandler = chargingHandler + super.init() + } + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "dev.fluttercommunity.plus/battery", binaryMessenger: registrar.messenger) + + let eventChannel = FlutterEventChannel(name: "dev.fluttercommunity.plus/charging", binaryMessenger: registrar.messenger) + + let chargingHandler = BatteryPlusChargingHandler() + + let instance = BatteryPlusMacosPlugin(chargingHandler: chargingHandler) + registrar.addMethodCallDelegate(instance, channel: channel) + + eventChannel.setStreamHandler(chargingHandler) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getBatteryLevel": + handleGetBatteryLevelMethodCall(result) + case "getBatteryState": + handleGetBatteryStateMethodCall(result) + default: + result(FlutterMethodNotImplemented) + } + } + + private func handleGetBatteryLevelMethodCall(_ result: FlutterResult){ + let level = getBatteryLevel() + if(level != -1){ + result(level) + + } else { + result("UNAVAILABLE") + } + + } + + private func getBatteryLevel()-> Int { + let powerSourceSnapshot = IOPSCopyPowerSourcesInfo().takeRetainedValue() + let sources = IOPSCopyPowerSourcesList(powerSourceSnapshot).takeRetainedValue() as Array + if sources.isEmpty { + return -1 + } + let description = IOPSGetPowerSourceDescription(powerSourceSnapshot, sources[0]).takeUnretainedValue() as! [String: AnyObject] + if let currentCapacity = description[kIOPSCurrentCapacityKey] as? Int { + return currentCapacity; + } + return -1 + } + + private func handleGetBatteryStateMethodCall(_ result: FlutterResult){ + let state = self.chargingHandler.getBatteryStatus() + result(state); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/battery_plus.podspec b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/battery_plus.podspec new file mode 100755 index 00000000..7f715df7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/battery_plus.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint battery_plus_macos.podspec' to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'battery_plus' + s.version = '0.0.1' + s.summary = 'Flutter Battery Plus' + s.description = <<-DESC +A Flutter plugin for accessing information about the battery state(full, charging, discharging). + DESC + s.homepage = 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus' + s.license = { :file => '../LICENSE' } + s.author = { 'Flutter Community' => 'authors@fluttercommunity.dev' } + s.source = { :path => 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus' } + s.source_files = 'Classes/**/*' + s.dependency 'FlutterMacOS' + + s.platform = :osx, '10.14' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.swift_version = '5.0' +end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/pubspec.yaml new file mode 100755 index 00000000..db772443 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/pubspec.yaml @@ -0,0 +1,49 @@ +name: battery_plus +description: Flutter plugin for accessing information about the battery state(full, charging, discharging). +version: 6.0.3 +homepage: https://github.com/fluttercommunity/plus_plugins +repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus/battery_plus +issue_tracker: https://github.com/fluttercommunity/plus_plugins/labels/battery_plus +topics: + - battery + - utils + +flutter: + plugin: + platforms: + android: + package: dev.fluttercommunity.plus.battery + pluginClass: BatteryPlusPlugin + ios: + pluginClass: FPPBatteryPlusPlugin + linux: + dartPluginClass: BatteryPlusLinuxPlugin + macos: + pluginClass: BatteryPlusMacosPlugin + web: + pluginClass: BatteryPlusWebPlugin + fileName: src/battery_plus_web.dart + windows: + pluginClass: BatteryPlusWindowsPlugin + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + battery_plus_platform_interface: ^2.0.1 + meta: ^1.8.0 + upower: ^0.7.0 + web: ^1.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + async: ^2.10.0 + flutter_lints: ^4.0.0 + mockito: ^5.4.0 + plugin_platform_interface: ^2.1.4 + +environment: + sdk: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.dart new file mode 100755 index 00000000..7f86b691 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.dart @@ -0,0 +1,64 @@ +import 'package:battery_plus/src/battery_plus_linux.dart'; +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:upower/upower.dart'; + +import 'battery_plus_linux_test.mocks.dart'; + +@GenerateMocks([UPowerClient, UPowerDevice]) +void main() { + test('registered instance', () { + BatteryPlusLinuxPlugin.registerWith(); + expect(BatteryPlatform.instance, isA()); + }); + test('battery level', () async { + final battery = BatteryPlusLinuxPlugin(); + battery.createClient = () { + return createMockClient(percentage: 56.78); + }; + expect(battery.batteryLevel, completion(equals(57))); + }); + + test('battery state', () async { + final battery = BatteryPlusLinuxPlugin(); + battery.createClient = () { + return createMockClient(state: UPowerDeviceState.charging); + }; + expect(battery.batteryState, completion(BatteryState.charging)); + }); + + test('battery state changes', () { + final battery = BatteryPlusLinuxPlugin(); + battery.createClient = () { + final client = createMockClient(state: UPowerDeviceState.charging); + final device = client.displayDevice; + when(device.propertiesChanged).thenAnswer((_) { + when(device.state).thenReturn(UPowerDeviceState.fullyCharged); + return Stream.value(['State']); + }); + return client; + }; + expect(battery.onBatteryStateChanged.isBroadcast, isTrue); + expect(battery.onBatteryStateChanged, + emitsInOrder([BatteryState.charging, BatteryState.full])); + }); +} + +MockUPowerClient createMockClient({ + double? percentage, + UPowerDeviceState? state, +}) { + final device = MockUPowerDevice(); + if (percentage != null) { + when(device.percentage).thenReturn(percentage); + } + if (state != null) { + when(device.state).thenReturn(state); + } + + final client = MockUPowerClient(); + when(client.displayDevice).thenReturn(device); + return client; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.mocks.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.mocks.dart new file mode 100755 index 00000000..4d1a2e7d --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.mocks.dart @@ -0,0 +1,245 @@ +// Mocks generated by Mockito 5.2.0 from annotations +// in battery_plus_linux/test/battery_plus_linux_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i3; + +import 'package:mockito/mockito.dart' as _i1; +import 'package:upower/src/upower_client.dart' as _i2; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types + +class _FakeUPowerKbdBacklight_0 extends _i1.Fake + implements _i2.UPowerKbdBacklight {} + +class _FakeUPowerDevice_1 extends _i1.Fake implements _i2.UPowerDevice {} + +/// A class which mocks [UPowerClient]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUPowerClient extends _i1.Mock implements _i2.UPowerClient { + MockUPowerClient() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.UPowerKbdBacklight get kbdBacklight => + (super.noSuchMethod(Invocation.getter(#kbdBacklight), + returnValue: _FakeUPowerKbdBacklight_0()) as _i2.UPowerKbdBacklight); + @override + set kbdBacklight(_i2.UPowerKbdBacklight? _kbdBacklight) => + super.noSuchMethod(Invocation.setter(#kbdBacklight, _kbdBacklight), + returnValueForMissingStub: null); + @override + String get daemonVersion => + (super.noSuchMethod(Invocation.getter(#daemonVersion), returnValue: '') + as String); + @override + bool get onBattery => + (super.noSuchMethod(Invocation.getter(#onBattery), returnValue: false) + as bool); + @override + bool get lidIsPresent => + (super.noSuchMethod(Invocation.getter(#lidIsPresent), returnValue: false) + as bool); + @override + bool get lidIsClosed => + (super.noSuchMethod(Invocation.getter(#lidIsClosed), returnValue: false) + as bool); + @override + List<_i2.UPowerDevice> get devices => + (super.noSuchMethod(Invocation.getter(#devices), + returnValue: <_i2.UPowerDevice>[]) as List<_i2.UPowerDevice>); + @override + _i2.UPowerDevice get displayDevice => + (super.noSuchMethod(Invocation.getter(#displayDevice), + returnValue: _FakeUPowerDevice_1()) as _i2.UPowerDevice); + @override + _i3.Stream<_i2.UPowerDevice> get deviceAdded => + (super.noSuchMethod(Invocation.getter(#deviceAdded), + returnValue: Stream<_i2.UPowerDevice>.empty()) + as _i3.Stream<_i2.UPowerDevice>); + @override + _i3.Stream<_i2.UPowerDevice> get deviceRemoved => + (super.noSuchMethod(Invocation.getter(#deviceRemoved), + returnValue: Stream<_i2.UPowerDevice>.empty()) + as _i3.Stream<_i2.UPowerDevice>); + @override + _i3.Stream> get propertiesChanged => (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: Stream>.empty()) as _i3.Stream>); + @override + _i3.Future connect() => + (super.noSuchMethod(Invocation.method(#connect, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future getCriticalAction() => + (super.noSuchMethod(Invocation.method(#getCriticalAction, []), + returnValue: Future.value('')) as _i3.Future); + @override + _i3.Future close() => (super.noSuchMethod(Invocation.method(#close, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); +} + +/// A class which mocks [UPowerDevice]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUPowerDevice extends _i1.Mock implements _i2.UPowerDevice { + MockUPowerDevice() { + _i1.throwOnMissingStub(this); + } + + @override + String get nativePath => + (super.noSuchMethod(Invocation.getter(#nativePath), returnValue: '') + as String); + @override + String get vendor => + (super.noSuchMethod(Invocation.getter(#vendor), returnValue: '') + as String); + @override + String get model => + (super.noSuchMethod(Invocation.getter(#model), returnValue: '') + as String); + @override + String get serial => + (super.noSuchMethod(Invocation.getter(#serial), returnValue: '') + as String); + @override + int get updateTime => + (super.noSuchMethod(Invocation.getter(#updateTime), returnValue: 0) + as int); + @override + _i2.UPowerDeviceType get type => (super.noSuchMethod(Invocation.getter(#type), + returnValue: _i2.UPowerDeviceType.unknown) as _i2.UPowerDeviceType); + @override + bool get powerSupply => + (super.noSuchMethod(Invocation.getter(#powerSupply), returnValue: false) + as bool); + @override + bool get hasHistory => + (super.noSuchMethod(Invocation.getter(#hasHistory), returnValue: false) + as bool); + @override + bool get hasStatistics => + (super.noSuchMethod(Invocation.getter(#hasStatistics), returnValue: false) + as bool); + @override + bool get online => + (super.noSuchMethod(Invocation.getter(#online), returnValue: false) + as bool); + @override + double get energy => + (super.noSuchMethod(Invocation.getter(#energy), returnValue: 0.0) + as double); + @override + double get energyEmpty => + (super.noSuchMethod(Invocation.getter(#energyEmpty), returnValue: 0.0) + as double); + @override + double get energyFull => + (super.noSuchMethod(Invocation.getter(#energyFull), returnValue: 0.0) + as double); + @override + double get energyFullDesign => (super + .noSuchMethod(Invocation.getter(#energyFullDesign), returnValue: 0.0) + as double); + @override + double get energyRate => + (super.noSuchMethod(Invocation.getter(#energyRate), returnValue: 0.0) + as double); + @override + double get voltage => + (super.noSuchMethod(Invocation.getter(#voltage), returnValue: 0.0) + as double); + @override + double get luminosity => + (super.noSuchMethod(Invocation.getter(#luminosity), returnValue: 0.0) + as double); + @override + int get timeToEmpty => + (super.noSuchMethod(Invocation.getter(#timeToEmpty), returnValue: 0) + as int); + @override + int get timeToFull => + (super.noSuchMethod(Invocation.getter(#timeToFull), returnValue: 0) + as int); + @override + double get percentage => + (super.noSuchMethod(Invocation.getter(#percentage), returnValue: 0.0) + as double); + @override + double get temperature => + (super.noSuchMethod(Invocation.getter(#temperature), returnValue: 0.0) + as double); + @override + bool get isPresent => + (super.noSuchMethod(Invocation.getter(#isPresent), returnValue: false) + as bool); + @override + _i2.UPowerDeviceState get state => + (super.noSuchMethod(Invocation.getter(#state), + returnValue: _i2.UPowerDeviceState.unknown) as _i2.UPowerDeviceState); + @override + bool get isRechargeable => (super + .noSuchMethod(Invocation.getter(#isRechargeable), returnValue: false) + as bool); + @override + double get capacity => + (super.noSuchMethod(Invocation.getter(#capacity), returnValue: 0.0) + as double); + @override + _i2.UPowerDeviceTechnology get technology => + (super.noSuchMethod(Invocation.getter(#technology), + returnValue: _i2.UPowerDeviceTechnology.unknown) + as _i2.UPowerDeviceTechnology); + @override + _i2.UPowerDeviceWarningLevel get warningLevel => + (super.noSuchMethod(Invocation.getter(#warningLevel), + returnValue: _i2.UPowerDeviceWarningLevel.unknown) + as _i2.UPowerDeviceWarningLevel); + @override + _i2.UPowerDeviceBatteryLevel get batteryLevel => + (super.noSuchMethod(Invocation.getter(#batteryLevel), + returnValue: _i2.UPowerDeviceBatteryLevel.unknown) + as _i2.UPowerDeviceBatteryLevel); + @override + String get iconName => + (super.noSuchMethod(Invocation.getter(#iconName), returnValue: '') + as String); + @override + _i3.Stream> get propertiesChanged => (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: Stream>.empty()) as _i3.Stream>); + @override + _i3.Future refresh() => + (super.noSuchMethod(Invocation.method(#refresh, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future> getHistory( + String? type, int? resolution, {int? timespan = 0}) => + (super.noSuchMethod( + Invocation.method( + #getHistory, [type, resolution], {#timespan: timespan}), + returnValue: Future>.value( + <_i2.UPowerDeviceHistoryRecord>[])) + as _i3.Future>); + @override + _i3.Future> getStatistics( + String? type) => + (super.noSuchMethod(Invocation.method(#getStatistics, [type]), + returnValue: Future>.value( + <_i2.UPowerDeviceStatisticsRecord>[])) + as _i3.Future>); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_test.dart new file mode 100755 index 00000000..fb1a7683 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_test.dart @@ -0,0 +1,66 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:async/async.dart'; +import 'package:battery_plus/battery_plus.dart'; +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +class MockBatteryPlatform + with MockPlatformInterfaceMixin + implements BatteryPlatform { + @override + Future get batteryLevel => Future.value(42); + + @override + Future get batteryState => Future.value(BatteryState.charging); + + @override + Stream get onBatteryStateChanged => Stream.fromIterable([ + BatteryState.unknown, + BatteryState.charging, + BatteryState.full, + BatteryState.discharging + ]); + + @override + Future get isInBatterySaveMode => Future.value(true); +} + +void main() { + late Battery battery; + late MockBatteryPlatform fakePlatform; + + setUpAll(() { + fakePlatform = MockBatteryPlatform(); + BatteryPlatform.instance = fakePlatform; + battery = Battery(); + }); + + test('batteryLevel', () async { + expect(await battery.batteryLevel, 42); + }); + + test('isInBatterySaveMode', () async { + expect(await battery.isInBatterySaveMode, true); + }); + + test('current state of the battery', () async { + expect(await battery.batteryState, BatteryState.charging); + }); + + test('receiving events of the battery state', () async { + final queue = StreamQueue(battery.onBatteryStateChanged); + + expect(await queue.next, BatteryState.unknown); + expect(await queue.next, BatteryState.charging); + expect(await queue.next, BatteryState.full); + expect(await queue.next, BatteryState.discharging); + + expect(await queue.hasNext, false); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/CMakeLists.txt new file mode 100755 index 00000000..b8f1d409 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.15) +set(PROJECT_NAME "battery_plus") +project(${PROJECT_NAME} LANGUAGES CXX) + +set(PLUGIN_NAME "${PROJECT_NAME}_plugin") + +add_library(${PLUGIN_NAME} SHARED + "${PLUGIN_NAME}.cpp" + "system_battery.cpp" +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) + +# List of absolute paths to libraries that should be bundled with the plugin +set(battery_plus_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/battery_plus_plugin.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/battery_plus_plugin.cpp new file mode 100755 index 00000000..868e5847 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/battery_plus_plugin.cpp @@ -0,0 +1,176 @@ +#include "include/battery_plus/battery_plus_windows_plugin.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "include/battery_plus/system_battery.h" + +namespace { + +typedef flutter::EventChannel FlEventChannel; +typedef flutter::EventSink FlEventSink; +typedef flutter::MethodCall FlMethodCall; +typedef flutter::MethodResult FlMethodResult; +typedef flutter::MethodChannel FlMethodChannel; +typedef flutter::StreamHandler FlStreamHandler; +typedef flutter::StreamHandlerError + FlStreamHandlerError; + +class BatteryPlusWindowsPlugin : public flutter::Plugin { +public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + + BatteryPlusWindowsPlugin(flutter::PluginRegistrarWindows *registrar); + ~BatteryPlusWindowsPlugin(); + +private: + void HandleMethodCall(const FlMethodCall &method_call, + std::unique_ptr result); + std::unique_ptr _methodChannel; + std::unique_ptr _eventChannel; +}; + +class BatteryStatusStreamHandler : public FlStreamHandler { +public: + BatteryStatusStreamHandler(flutter::PluginRegistrarWindows *registrar); + +protected: + void AddStatusEvent(BatteryStatus status); + + std::unique_ptr + OnListenInternal(const flutter::EncodableValue *arguments, + std::unique_ptr &&events) override; + + std::unique_ptr + OnCancelInternal(const flutter::EncodableValue *arguments) override; + +private: + int _delegate = -1; + SystemBattery _battery; + std::unique_ptr _events; + flutter::PluginRegistrarWindows *_registrar = nullptr; +}; + +void BatteryPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar) { + registrar->AddPlugin(std::make_unique(registrar)); +} + +BatteryPlusWindowsPlugin::BatteryPlusWindowsPlugin( + flutter::PluginRegistrarWindows *registrar) { + _methodChannel = std::make_unique( + registrar->messenger(), "dev.fluttercommunity.plus/battery", + &flutter::StandardMethodCodec::GetInstance()); + + _methodChannel->SetMethodCallHandler([this](const auto &call, auto result) { + HandleMethodCall(call, std::move(result)); + }); + + _eventChannel = std::make_unique( + registrar->messenger(), "dev.fluttercommunity.plus/charging", + &flutter::StandardMethodCodec::GetInstance()); + + _eventChannel->SetStreamHandler( + std::make_unique(registrar)); +} + +BatteryPlusWindowsPlugin::~BatteryPlusWindowsPlugin() {} + +BatteryStatusStreamHandler::BatteryStatusStreamHandler( + flutter::PluginRegistrarWindows *registrar) + : _registrar(registrar) {} + +void BatteryStatusStreamHandler::AddStatusEvent(BatteryStatus status) { + if (status != BatteryStatus::Error) { + _events->Success(_battery.GetStatusString()); + } else { + _events->Error(std::to_string(_battery.GetError()), + _battery.GetErrorString()); + } +} + +std::unique_ptr +BatteryStatusStreamHandler::OnListenInternal( + const flutter::EncodableValue *arguments, + std::unique_ptr &&events) { + _events = std::move(events); + + HWND hwnd = _registrar->GetView()->GetNativeWindow(); + BatteryStatusCallback callback = std::bind( + &BatteryStatusStreamHandler::AddStatusEvent, this, std::placeholders::_1); + + if (!_battery.StartListen(hwnd, callback)) { + return std::make_unique( + std::to_string(_battery.GetError()), _battery.GetErrorString(), + nullptr); + } + + _delegate = _registrar->RegisterTopLevelWindowProcDelegate( + [this](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { + _battery.ProcessMsg(hwnd, message, wparam, lparam); + return std::nullopt; + }); + + AddStatusEvent(_battery.GetStatus()); + return nullptr; +} + +std::unique_ptr +BatteryStatusStreamHandler::OnCancelInternal( + const flutter::EncodableValue *arguments) { + _registrar->UnregisterTopLevelWindowProcDelegate(_delegate); + if (!_battery.StopListen()) { + return std::make_unique( + std::to_string(_battery.GetError()), _battery.GetErrorString(), + nullptr); + } + _delegate = -1; + _events.reset(); + return nullptr; +} + +void BatteryPlusWindowsPlugin::HandleMethodCall( + const FlMethodCall &method_call, std::unique_ptr result) { + if (method_call.method_name().compare("isInBatterySaveMode") == 0) { + SystemBattery battery; + int batteryStatus = battery.GetBatterySaveMode(); + if (batteryStatus == 0 || batteryStatus == 1) { + bool isBatteryMode = batteryStatus == 1; + result->Success(flutter::EncodableValue(isBatteryMode)); + } else { + result->Error(std::to_string(battery.GetError()), + battery.GetErrorString()); + } + } else if (method_call.method_name().compare("getBatteryLevel") == 0) { + SystemBattery battery; + int level = battery.GetLevel(); + if (level >= 0) { + result->Success(flutter::EncodableValue(level)); + } else { + result->Error(std::to_string(battery.GetError()), + battery.GetErrorString()); + } + } else if (method_call.method_name().compare("getBatteryState") == 0) { + SystemBattery battery; + result->Success(flutter::EncodableValue(battery.GetStatusString())); + } else { + result->NotImplemented(); + } +} + +} // namespace + +void BatteryPlusWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + BatteryPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h new file mode 100755 index 00000000..9d8d9226 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h @@ -0,0 +1,23 @@ +#ifndef FLUTTER_PLUGIN_BATTERY_PLUS_PLUGIN_H_ +#define FLUTTER_PLUGIN_BATTERY_PLUS_PLUGIN_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void BatteryPlusWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_PLUGIN_BATTERY_PLUS_WINDOWS_PLUGIN_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/system_battery.h b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/system_battery.h new file mode 100755 index 00000000..9e58f0e2 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/system_battery.h @@ -0,0 +1,37 @@ +#ifndef FLUTTER_PLUGIN_BATTERY_PLUS_SYSTEM_BATTERY_H_ +#define FLUTTER_PLUGIN_BATTERY_PLUS_SYSTEM_BATTERY_H_ + +#include +#include + +#include +#include + +enum class BatteryStatus { Full, Charging, Discharging, Error, Unknown }; + +typedef std::function BatteryStatusCallback; + +class SystemBattery { +public: + SystemBattery(); + ~SystemBattery(); + + int GetBatterySaveMode() const; + int GetLevel() const; + + BatteryStatus GetStatus() const; + std::string GetStatusString() const; + + int GetError() const; + std::string GetErrorString() const; + + bool StartListen(HWND hwnd, BatteryStatusCallback callback); + void ProcessMsg(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); + bool StopListen(); + +private: + HPOWERNOTIFY _notifier = nullptr; + BatteryStatusCallback _callback = nullptr; +}; + +#endif // FLUTTER_PLUGIN_BATTERY_PLUS_SYSTEM_BATTERY_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/system_battery.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/system_battery.cpp new file mode 100755 index 00000000..b769196b --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/system_battery.cpp @@ -0,0 +1,125 @@ +#include "include/battery_plus/system_battery.h" + +#include + +namespace { +enum ACLineStatus { + Offline = 0, + Online = 1, +}; + +enum BatteryLevel { + Empty = 0, + Full = 100, + Unknown = 255, +}; + +enum BatteryFlag { + High = 1, // the battery capacity is at more than 66 percent + Low = 2, // the battery capacity is at less than 33 percent + Critical = 4, // the battery capacity is at less than five percent + Charging = 8, + NoBattery = 128 // no system battery +}; + +bool GetBatteryStatus(LPSYSTEM_POWER_STATUS lpStatus) { + return GetSystemPowerStatus(lpStatus) != 0; +} + +bool IsValidBatteryStatus(LPSYSTEM_POWER_STATUS lpStatus) { + return lpStatus->BatteryFlag != NoBattery && + lpStatus->BatteryLifePercent != Unknown; +} +} // namespace + +SystemBattery::SystemBattery() {} + +SystemBattery::~SystemBattery() { StopListen(); } + +int SystemBattery::GetBatterySaveMode() const { + SYSTEM_POWER_STATUS status; + if (!GetBatteryStatus(&status)) { + return -1; + } + return status.SystemStatusFlag; +} + +int SystemBattery::GetLevel() const { + SYSTEM_POWER_STATUS status; + if (!GetBatteryStatus(&status) || !IsValidBatteryStatus(&status)) { + return -1; + } + return status.BatteryLifePercent; +} + +BatteryStatus SystemBattery::GetStatus() const { + SYSTEM_POWER_STATUS status; + if (!GetBatteryStatus(&status)) { + return BatteryStatus::Error; + } + if (IsValidBatteryStatus(&status)) { + if (status.ACLineStatus == Online) { + if (status.BatteryLifePercent == Full) { + return BatteryStatus::Full; + } else if (status.BatteryFlag & Charging) { + return BatteryStatus::Charging; + } + } else if (status.ACLineStatus == Offline) { + if (!(status.BatteryFlag & Charging)) { + return BatteryStatus::Discharging; + } + } + } + return BatteryStatus::Unknown; +} + +std::string SystemBattery::GetStatusString() const { + switch (GetStatus()) { + case BatteryStatus::Charging: + return "charging"; + case BatteryStatus::Discharging: + return "discharging"; + case BatteryStatus::Full: + return "full"; + case BatteryStatus::Unknown: + default: + return "unknown"; + } +} + +int SystemBattery::GetError() const { return GetLastError(); } + +std::string SystemBattery::GetErrorString() const { + // ### TODO: FormatMessage() + return "GetSystemPowerStatus() failed"; +} + +bool SystemBattery::StartListen(HWND hwnd, BatteryStatusCallback callback) { + if (_notifier) { + return false; + } + _callback = callback; + _notifier = RegisterPowerSettingNotification(hwnd, &GUID_ACDC_POWER_SOURCE, + DEVICE_NOTIFY_WINDOW_HANDLE); + return _notifier != nullptr; +} + +void SystemBattery::ProcessMsg(HWND hwnd, UINT message, WPARAM wparam, + LPARAM lparam) { + if (!_callback) { + return; + } + if (message == WM_POWERBROADCAST && wparam == PBT_APMPOWERSTATUSCHANGE) { + _callback(GetStatus()); + } +} + +bool SystemBattery::StopListen() { + if (!_notifier) { + return false; + } + HPOWERNOTIFY notifier = nullptr; + std::swap(notifier, _notifier); + _callback = nullptr; + return UnregisterPowerSettingNotification(notifier) != 0; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus deleted file mode 120000 index 1dfc8a9a..00000000 --- a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/ \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/CHANGELOG.md b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/CHANGELOG.md new file mode 100755 index 00000000..02a57c8d --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/CHANGELOG.md @@ -0,0 +1,507 @@ +## 6.0.5 + + - **DOCS**(connectivity_plus): Update plugin requirements in README ([#3160](https://github.com/fluttercommunity/plus_plugins/issues/3160)). ([277f8b6b](https://github.com/fluttercommunity/plus_plugins/commit/277f8b6ba9ee6e7e5e3b1cce3e5eb8416830ba6b)) + +## 6.0.4 + + - **CHORE**(connectivity_plus): Use `>=0.5.0 < 2.0.0` version range for package:web. + - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) + - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) + +## 6.0.3 + + - **FIX**(connectivity_plus): Ensure Connectivity on Android is correctly reported when lost ([#2836](https://github.com/fluttercommunity/plus_plugins/issues/2836)). ([2aa6ad7a](https://github.com/fluttercommunity/plus_plugins/commit/2aa6ad7a1c05d35b894e6cef515bd9dfa49351dd)) + +## 6.0.2 + + - **REFACTOR**(connectivity_plus): remove ReachabilityConnectivityProvider and ReachabilitySwift dependency ([#2813](https://github.com/fluttercommunity/plus_plugins/issues/2813)). ([f9ad927f](https://github.com/fluttercommunity/plus_plugins/commit/f9ad927f5c18f8ed8d4c22a24476430239c13492)) + - **REFACTOR**(connectivity_plus): Migrate Android example to use the new plugins declaration ([#2771](https://github.com/fluttercommunity/plus_plugins/issues/2771)). ([04200c23](https://github.com/fluttercommunity/plus_plugins/commit/04200c2311e8dd581980ed19f8ebd24d0afd1512)) + - **FIX**(connectivity_plus): WASM-compatible conditional imports ([#2825](https://github.com/fluttercommunity/plus_plugins/issues/2825)). ([6bee4a7e](https://github.com/fluttercommunity/plus_plugins/commit/6bee4a7e02d681ce94d8bd95c4399d844b0ceb27)) + - **FIX**(connectivity_plus): Improve iOS PathMonitorConnectivityProvider implementation and documentation ([#2763](https://github.com/fluttercommunity/plus_plugins/issues/2763)). ([c850d58e](https://github.com/fluttercommunity/plus_plugins/commit/c850d58ed9f422182c8f77583a43bcb13d5d979f)) + - **DOCS**(connectivity_plus): Document supported ConnectivityResult per platform ([#2780](https://github.com/fluttercommunity/plus_plugins/issues/2780)). ([1c4aec01](https://github.com/fluttercommunity/plus_plugins/commit/1c4aec019e74433a2b1174d75522b5abb0c9d9b4)) + - **DOCS**(connectivity_plus): Update README for more clarity ([#2770](https://github.com/fluttercommunity/plus_plugins/issues/2770)). ([8fb738e2](https://github.com/fluttercommunity/plus_plugins/commit/8fb738e2b8f5534db8f1c0fbbeae1a51cf03d099)) + - **DOCS**(connectivity_plus): Specify behavior when there is no connectivity ([#2753](https://github.com/fluttercommunity/plus_plugins/issues/2753)). ([8f132a23](https://github.com/fluttercommunity/plus_plugins/commit/8f132a23a0424299c5e9b946171164bc66710540)) + - **DOCS**(connectivity_plus): Improve documentation onConnectivityChanged method ([#2746](https://github.com/fluttercommunity/plus_plugins/issues/2746)). ([9ea21fbd](https://github.com/fluttercommunity/plus_plugins/commit/9ea21fbdbb9974077375f803f5bb3c57abcb6488)) + +## 6.0.1 + +> Note: This release has breaking changes. + +> Plugin now requires the following: +> - Flutter >=3.19.0 +> - Dart >=3.3.0 +> - compileSDK 34 for Android part +> - Java 17 for Android part +> - Gradle 8.4 for Android part + +In this release plugin migrated to package:web, meaning that it now supports WASM! + +- **BREAKING** **FEAT**(connectivity_plus): support multiple connectivity types at the same time ([#2599](https://github.com/fluttercommunity/plus_plugins/issues/2599)). ([5b477468](https://github.com/fluttercommunity/plus_plugins/commit/5b4774683d6e186fbd69cf4208302221f52aa54d)) +- **BREAKING** **FEAT**(connectivity_plus): Migrate to package:web ([#2621](https://github.com/fluttercommunity/plus_plugins/issues/2621)). ([fbc8e61c](https://github.com/fluttercommunity/plus_plugins/commit/fbc8e61c4f8996d6ba47622de191a83dc2fe1882)) +- **BREAKING** **BUILD**(connectivity_plus): Target Java 17 on Android ([2413e45e](https://github.com/fluttercommunity/plus_plugins/commit/2413e45e88fa6a431c29f8e6240780e20c405453)) +- **BREAKING** **BUILD**(connectivity_plus): Update to target and compile SDK 34 ([#2701](https://github.com/fluttercommunity/plus_plugins/pull/2701)). ([7ddd749](https://github.com/fluttercommunity/plus_plugins/commit/7ddd74989d2921af706f5e7a1aa32e41159ce13f)) +- **BREAKING** **REFACTOR**(connectivity_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2588](https://github.com/fluttercommunity/plus_plugins/issues/2588)). ([f6fe62d5](https://github.com/fluttercommunity/plus_plugins/commit/f6fe62d5f4d87c93e0f974e96bbd47ff453937d9)) +- **FIX**(connectivity_plus): Emit event with types on Android when subscribing to onConnectivityChanged ([#2721](https://github.com/fluttercommunity/plus_plugins/issues/2721)). ([5a81e7ef](https://github.com/fluttercommunity/plus_plugins/commit/5a81e7ef75d75852935f7a095e5b426d534edff9)) +- **FIX**(connectivity_plus): Fix connectivity state update on Android when network is lost ([#2673](https://github.com/fluttercommunity/plus_plugins/issues/2673)). ([21191682](https://github.com/fluttercommunity/plus_plugins/commit/2119168267e436e5900ea09cf68dd110e51b01e0)) +- **FIX**(connectivity_plus): Return valid connection type when only one available ([#2668](https://github.com/fluttercommunity/plus_plugins/issues/2668)). ([81026a4c](https://github.com/fluttercommunity/plus_plugins/commit/81026a4c6c07cb610299a8f17db69c518475a675)) +- **FIX**(connectivity_plus): Add iOS Privacy Info ([#2581](https://github.com/fluttercommunity/plus_plugins/issues/2581)). ([707fab70](https://github.com/fluttercommunity/plus_plugins/commit/707fab70eb1dd262226158be97586a67eec03dd0)) +- **FIX**(connectivity_plus): Fix iOS example app name ([#2722](https://github.com/fluttercommunity/plus_plugins/issues/2722)). ([2441accd](https://github.com/fluttercommunity/plus_plugins/commit/2441accdffc3bc86f5e74db6c682d0dd4fbd6813)) +- **DOCS**(connectivity_plus): Update documentation to address API changes ([#2719](https://github.com/fluttercommunity/plus_plugins/issues/2719)). ([59b9b341](https://github.com/fluttercommunity/plus_plugins/commit/59b9b3417cd0387d8a5f9e857eb350b4048dc68c)) + +## 6.0.0 + +> Note: DO NOT USE THIS RELEASE. It is invalid due to a publishing issue + +## 5.0.2 + + - **FIX**(connectivity_plus): Return correct connection state on Linux ([#2371](https://github.com/fluttercommunity/plus_plugins/issues/2371)). ([26576d83](https://github.com/fluttercommunity/plus_plugins/commit/26576d838be3b39121fd77ab33f49fc1fff1a97f)) + +## 5.0.1 + + - **FIX**(connectivity_plus): Fix CHANGELOG to not mention Kotlin requirement ([#2246](https://github.com/fluttercommunity/plus_plugins/issues/2246)). ([e489d4aa](https://github.com/fluttercommunity/plus_plugins/commit/e489d4aa7a223b152b89b6c33ae994e8a73679bd)) + +## 5.0.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**(connectivity_plus): Bump min iOS to 12 to not crash after builds with Xcode 15 ([#2169](https://github.com/fluttercommunity/plus_plugins/issues/2169)). ([cf7d93fb](https://github.com/fluttercommunity/plus_plugins/commit/cf7d93fbfc76830acf2db755543cf4235a49df60)) + - **FIX**(connectivity_plus): Revert bump compileSDK to 34 ([#2229](https://github.com/fluttercommunity/plus_plugins/issues/2229)). ([01df65ce](https://github.com/fluttercommunity/plus_plugins/commit/01df65ce0268093de5dd381c84d251668dc95984)) + - **FEAT**(connectivity_plus): Remove deprecated VALID_ARCHS iOS property ([#2021](https://github.com/fluttercommunity/plus_plugins/issues/2021)). ([ee89d583](https://github.com/fluttercommunity/plus_plugins/commit/ee89d5836c7e598fce07d89e82a2d127ddfacbf8)) + + +## 4.0.2 + + - **FIX**(connectivity_plus): Downgrade js version to work with Flutter 3.3.10 ([#1989](https://github.com/fluttercommunity/plus_plugins/issues/1989)). ([42938c0c](https://github.com/fluttercommunity/plus_plugins/commit/42938c0c03132f7f50fa047c2970660d2720d320)) + - **FIX**(connectivity_plus): Regenerate iOS and MacOS example apps ([#1874](https://github.com/fluttercommunity/plus_plugins/issues/1874)). ([fc22e54e](https://github.com/fluttercommunity/plus_plugins/commit/fc22e54ec166d37d4326a9271677054fd34ccc3c)) + - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) + +## 4.0.1 + + - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) + +## 4.0.0 + +> Note: This release has breaking changes. + + - **CHORE**(connectivity_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 + - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. + - **BREAKING** **CHORE**(connectivity_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1782). + +## 3.0.6 + + - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). + +## 3.0.5 + + - **FIX**(connectivity_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1701). + +## 3.0.4 + + - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). + - **DOCS**(connectivity_plus): Documentation added for the missing network interface enums (#1524). + +## 3.0.3 + + - **FIX**: Do not return ConnectivityResult.none on iOS and MacOS with VPN (#1335). + - **DOCS**: Updates for READMEs and website pages (#1389). + +## 3.0.2 + + - **FIX**: Add connectivity_plus_web export (#1278). + +## 3.0.1 + + - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). + +## 3.0.0 + +> Note: This release has breaking changes. + + - **FIX**: lint warnings - add missing dependency for tests (#1233). + - **BREAKING** **REFACTOR**: two-package federated architecture (#1227). + +## 2.3.9 + + - **CHORE**: Version tagging using melos. + +## 2.3.8 + +- Discard unused warnings for `ensurePathMonitor` & `ensureReachability` call in iOS. + +## 2.3.7 + +- iOS: Reduce compiler warnings + +## 2.3.6+1 + +- Add issue_tracker link. + +## 2.3.6 + +- Web: Fix Bad state: Stream has already been listened to (#943) + +## 2.3.5 + +- Stop sending events once flutter engine detached on iOS/macOS (#865) + +## 2.3.4 + +- Disables internal use of `NetworkInformationAPI` which is still experimental + +## 2.3.3 + +- macOS: Send events on main thread + +## 2.3.2 + +- iOS: Send events on main thread (#846) + +## 2.3.1 + +- Update flutter_lints to 2.0.1 +- Update dev dependencies + +## 2.3.0 + +- Add iOS ConnectivityProvider based on NWPathMonitor for iOS 12+. + +## 2.2.2 + +- Reachability.swift ".unavailable" for iOS is deprecated. + +## 2.2.1 + +- Bump `nm` plugin to 0.5.0 (connectivity_plus_linux) +- Fix embedding issue in example + +## 2.2.0 + +- Add bluetooth as connectivity result. Supported on Android, Linux, and Web + +## 2.1.0 + +- Migrated iOS plugin to Swift +- Removed dependency to old Reachability pod +- Added dependency to Reachability.swift pod + +## 2.0.3 + +- Add Gradle wrapper to Android plugin + +## 2.0.2 + +- Fix for error: lambda expressions are not supported in -source 7 + +## 2.0.1 + +- Upgrade Android compile SDK version +- Several code improvements + +## 2.0.0 + +- Remove deprecated method `registerWith` (of Android v1 embedding) + +## 1.4.0 + +- [MacOS]: Backport to macOS 10.11 + +## 1.3.0 + +- Add ethernet as connectivity result. Supported on Android, iOS, Windows, Linux, macOS, and Web + +## 1.2.0 + +- migrate integration_test to flutter sdk + +## 1.1.0 + +- Add ethernet as connectivity result. Supported on Android, Linux, macOS, and Web + +## 1.0.8 + +- Web: Fix to show `ConnectivityResult.mobile` instead of `ConnectivityResult.wifi` when the network is connected to 4g + +## 1.0.7 + +- Android: Fix to detect no-network when Wi-Fi is disconnected on Android M and above + +## 1.0.6 + +- Android: Fix unregisterReceiver call for API < N + +## 1.0.5 + +- Android: Fix memory leak from registered receiver +- Android: Fix gradle crash due to previous update in version 1.0.4 + +## 1.0.4 + +- Android: Add explicit compiler version to avoid warnings + +## 1.0.3 + +- Android: migrate to mavenCentral + +## 1.0.2 + +- Fix ios bug https://github.com/fluttercommunity/plus_plugins/issues/198 +- Update android https://github.com/fluttercommunity/plus_plugins/issues/62 +- Update Web class naming conflict https://github.com/fluttercommunity/plus_plugins/issues/260 + +## 1.0.1 + +- Improve documentation + +## 1.0.0 + +- Migrated to null safety + +## 0.8.1 + +- Address pub score + +## 0.8.0 + +- Add Windows support (`connectivity_plus_windows`). +- Removed members that were moved to network_info_plus + +## 0.7.2 + +- Deprecated the following members (use network_info_plus instead): + - getWifiBSSID() + - getWifiIP() + - requestLocationServiceAuthorization() + - getLocationServiceAuthorization() + +## 0.7.1 + +- Bump linux version. + +## 0.7.0 + +- Add Linux support (`connectivity_plus_linux`). + +## 0.6.0 + +- Fix issue #56: Rename Android and iOS classes and Method Channel to avoid + collision with the original connectivity package. + +## 0.5.0 + +- Transfer to plus-plugins monorepo + +## 0.4.9+2 + +- Update package:e2e to use package:integration_test + +## 0.4.9+1 + +- Update package:e2e reference to use the local version in the flutter/plugins + repository. + +## 0.4.9 + +- Add support for `web` (by endorsing `connectivity_for_web` 0.3.0) + +## 0.4.8+6 + +- Update lower bound of dart dependency to 2.1.0. + +## 0.4.8+5 + +- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). + +## 0.4.8+4 + +- Bump the minimum Flutter version to 1.12.13+hotfix.5. +- Clean up various Android workarounds no longer needed after framework v1.12. +- Complete v2 embedding support. +- Fix CocoaPods podspec lint warnings. + +## 0.4.8+3 + +- Replace deprecated `getFlutterEngine` call on Android. + +## 0.4.8+2 + +- Remove hard coded ios workspace setting of the example app. + +## 0.4.8+1 + +- Make the pedantic dev_dependency explicit. + +## 0.4.8 + +- Adds macOS as an endorsed platform. + +## 0.4.7 + +- Migrate the plugin to use the ConnectivityPlatform.instance defined in the connectivity_plus_platform_interface package. + +## 0.4.6+2 + +- Migrate deprecated BinaryMessages to ServicesBinding.instance.defaultBinaryMessenger. +- Bump Flutter SDK to 1.12.13+hotfix.5 or greater (current stable). + +## 0.4.6+1 + +- Remove the deprecated `author:` field from pubspec.yaml +- Migrate the plugin to the pubspec platforms manifest. +- Require Flutter SDK 1.10.0 or greater. + +## 0.4.6 + +- Add macOS support. + +## 0.4.5+8 + +- Update documentation to explain when connectivity updates are received on Android. + +## 0.4.5+7 + +- Fix unawaited futures in the example app and tests. + +## 0.4.5+6 + +- Fix singleton Reachability problem on iOS. + +## 0.4.5+5 + +- Add an analyzer check for the public documentation. + +## 0.4.5+4 + +- Stability and Maintainability: update documentations. + +## 0.4.5+3 + +- Remove AndroidX warnings. + +## 0.4.5+2 + +- Include lifecycle dependency as a compileOnly one on Android to resolve + potential version conflicts with other transitive libraries. + +## 0.4.5+1 + +- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. + +## 0.4.5 + +- Support the v2 Android embedder. + +## 0.4.4+1 + +- Update and migrate iOS example project. +- Define clang module for iOS. + +## 0.4.4 + +- Add `requestLocationServiceAuthorization` to request location authorization on iOS. +- Add `getLocationServiceAuthorization` to get location authorization status on iOS. +- Update README: add more information on iOS 13 updates with CNCopyCurrentNetworkInfo. + +## 0.4.3+7 + +- Update README with the updated information about CNCopyCurrentNetworkInfo on iOS 13. + +## 0.4.3+6 + +- [Android] Fix the invalid suppression check (it should be "deprecation" not "deprecated"). + +## 0.4.3+5 + +- [Android] Added API 29 support for `check()`. +- [Android] Suppress warnings for using deprecated APIs. + +## 0.4.3+4 + +- [Android] Updated logic to retrieve network info. + +## 0.4.3+3 + +- Support for TYPE_MOBILE_HIPRI on Android. + +## 0.4.3+2 + +- Add missing template type parameter to `invokeMethod` calls. + +## 0.4.3+1 + +- Fixes lint error by using `getApplicationContext()` when accessing the Wifi Service. + +## 0.4.3 + +- Add getWifiBSSID to obtain current wifi network's BSSID. + +## 0.4.2+2 + +- Add integration test. + +## 0.4.2+1 + +- Bump the minimum Flutter version to 1.2.0. +- Add template type parameter to `invokeMethod` calls. + +## 0.4.2 + +- Adding getWifiIP() to obtain current wifi network's IP. + +## 0.4.1 + +- Add unit tests. + +## 0.4.0+2 + +- Log a more detailed warning at build time about the previous AndroidX + migration. + +## 0.4.0+1 + +- Updated `Connectivity` to a singleton. + +## 0.4.0 + +- **Breaking change**. Migrate from the deprecated original Android Support + Library to AndroidX. This shouldn't result in any functional changes, but it + requires any Android apps using this plugin to [also + migrate](https://developer.android.com/jetpack/androidx/migrate) if they're + using the original support library. + +## 0.3.2 + +- Adding getWifiName() to obtain current wifi network's SSID. + +## 0.3.1 + +- Updated Gradle tooling to match Android Studio 3.1.2. + +## 0.3.0 + +- **Breaking change**. Set SDK constraints to match the Flutter beta release. + +## 0.2.1 + +- Fixed warnings from the Dart 2.0 analyzer. +- Simplified and upgraded Android project template to Android SDK 27. +- Updated package description. + +## 0.2.0 + +- **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin + 3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in + order to use this version of the plugin. Instructions can be found + [here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1). + +## 0.1.1 + +- Add FLT prefix to iOS types. + +## 0.1.0 + +- Breaking API change: Have a Connectivity class instead of a top level function +- Introduce ability to listen for network state changes + +## 0.0.1 + +- Initial release diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/LICENSE b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/LICENSE new file mode 100755 index 00000000..7b995420 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/LICENSE @@ -0,0 +1,27 @@ +Copyright 2017 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/README.md new file mode 100755 index 00000000..8eb6ece0 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/README.md @@ -0,0 +1,139 @@ +# connectivity_plus + +[![pub package](https://img.shields.io/pub/v/connectivity_plus.svg)](https://pub.dev/packages/connectivity_plus) +[![pub points](https://img.shields.io/pub/points/connectivity_plus?color=2E8B57&label=pub%20points)](https://pub.dev/packages/connectivity_plus/score) +[![connectivity_plus](https://github.com/fluttercommunity/plus_plugins/actions/workflows/connectivity_plus.yaml/badge.svg)](https://github.com/fluttercommunity/plus_plugins/actions/workflows/connectivity_plus.yaml) + +[](https://flutter.dev/docs/development/packages-and-plugins/favorites) + +This plugin allows Flutter apps to discover network connectivity types that can be used. + +> **Note** +> +> You should not rely on the current connectivity status to decide whether you can reliably make a network request. Always guard your app code against timeouts and errors that might come from the network layer. +> Connection type availability does not guarantee that there is an Internet access. For example, the plugin might return Wi-Fi connection type, but it might be a connection with no Internet access due to network requirements (like on hotel Wi-Fi networks where user often needs to go through a captive portal to authorize first). +> + +## Platform Support + +| Android | iOS | MacOS | Web | Linux | Windows | +| :-----: | :-: | :---: | :-: | :---: | :-----: | +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | + +## Requirements + +- Flutter >=3.7.0 +- Dart >=3.2.0 <4.0.0 +- iOS >=12.0 +- MacOS >=10.14 +- Android `compileSDK` 34 +- Java 17 +- Android Gradle Plugin >=8.3.0 +- Gradle wrapper >=8.4 + +## Usage + +Sample usage to check currently available connection types: + +```dart +import 'package:connectivity_plus/connectivity_plus.dart'; + +final List connectivityResult = await (Connectivity().checkConnectivity()); + +// This condition is for demo purposes only to explain every connection type. +// Use conditions which work for your requirements. +if (connectivityResult.contains(ConnectivityResult.mobile)) { + // Mobile network available. +} else if (connectivityResult.contains(ConnectivityResult.wifi)) { + // Wi-fi is available. + // Note for Android: + // When both mobile and Wi-Fi are turned on system will return Wi-Fi only as active network type +} else if (connectivityResult.contains(ConnectivityResult.ethernet)) { + // Ethernet connection available. +} else if (connectivityResult.contains(ConnectivityResult.vpn)) { + // Vpn connection active. + // Note for iOS and macOS: + // There is no separate network interface type for [vpn]. + // It returns [other] on any device (also simulator) +} else if (connectivityResult.contains(ConnectivityResult.bluetooth)) { + // Bluetooth connection available. +} else if (connectivityResult.contains(ConnectivityResult.other)) { + // Connected to a network which is not in the above mentioned networks. +} else if (connectivityResult.contains(ConnectivityResult.none)) { + // No available network types +} +``` + +You can also listen for active connectivity types changes by subscribing to the stream +exposed by the plugin. + +This method should ensure emitting only distinct values. + +```dart +import 'package:connectivity_plus/connectivity_plus.dart'; + +@override +initState() { + super.initState(); + + StreamSubscription> subscription = Connectivity().onConnectivityChanged.listen((List result) { + // Received changes in available connectivity types! + }); +} + +// Be sure to cancel subscription after you are done +@override +dispose() { + subscription.cancel(); + super.dispose(); +} +``` + +## Platform Support + +The following table shows which `ConnectivityResult` values are supported per platform. + +| | Android | iOS | Web | MacOS | Windows | Linux | +|-----------|:-------:|:---:|:---:|:-----:|:-------:|:-----:| +| wifi | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| bluetooth | :white_check_mark: | | | | | :white_check_mark: | +| ethernet | :white_check_mark: | :white_check_mark: | | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| mobile | :white_check_mark: | :white_check_mark: | | :white_check_mark: | | | +| vpn | :white_check_mark: | | | | :white_check_mark: | :white_check_mark: | +| other | :white_check_mark: | :white_check_mark: | | :white_check_mark: | :white_check_mark: | :white_check_mark: | + +_`none` is supported on all platforms by default._ + +### Android + +Connectivity changes are no longer communicated to Android apps in the background starting with Android O (8.0). You should always check for connectivity status when your app is resumed. The broadcast is only useful when your application is in the foreground. + +### iOS & MacOS + +On iOS simulators, the connectivity types stream might not update when Wi-Fi status changes. This is a known issue. + +Starting with iOS 12 and MacOS 10.14, the implementation uses `NWPathMonitor` to obtain the enabled connectivity types. We noticed that this observer can give multiple or unreliable results. For example, reporting connectivity "none" followed by connectivity "wifi" right after reconnecting. + +We recommend to use the `onConnectivityChanged` with this limitation in mind, as the method doesn't filter events, nor it ensures distinct values. + +### Web + +In order to retrieve information about the quality/speed of a browser's connection, the web implementation of the `connectivity` plugin uses the browser's [**NetworkInformation** Web API](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation), which as of this writing (June 2020) is still "experimental", and not available in all browsers: + +![Data on support for the netinfo feature across the major browsers from caniuse.com](https://caniuse.bitsofco.de/image/netinfo.png) + +On desktop browsers, this API only returns a very broad set of connectivity statuses (One of `'slow-2g', '2g', '3g', or '4g'`), and may _not_ provide a Stream of changes. Firefox still hasn't enabled this feature by default. + +**Fallback to `navigator.onLine`** + +For those browsers where the NetworkInformation Web API is not available, the plugin falls back to the [**NavigatorOnLine** Web API](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine), which is more broadly supported: + +![Data on support for the online-status feature across the major browsers from caniuse.com](https://caniuse.bitsofco.de/image/online-status.png) + +The NavigatorOnLine API is [provided by `dart:html`](https://api.dart.dev/stable/2.7.2/dart-html/Navigator/onLine.html), and only supports a boolean connectivity status (either online or offline), with no network speed information. In those cases the plugin will return either `wifi` (when the browser is online) or `none` (when it's not). + +Other than the approximate "downlink" speed, where available, and due to security and privacy concerns, **no Web browser will provide** any specific information about the actual network your users' device is connected to, like **the SSID on a Wi-Fi, or the MAC address of their device.** + +## Learn more + +- [API Documentation](https://pub.dev/documentation/connectivity_plus/latest/connectivity_plus/connectivity_plus-library.html) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/build.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/build.gradle new file mode 100755 index 00000000..6d8c5881 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/build.gradle @@ -0,0 +1,41 @@ +group 'dev.fluttercommunity.plus.connectivity' +version '1.0-SNAPSHOT' + +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.3.1' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdk 34 + + namespace 'dev.fluttercommunity.plus.connectivity' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + defaultConfig { + minSdk 19 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle.properties new file mode 100755 index 00000000..8bd86f68 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..cae4528d --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/settings.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/settings.gradle new file mode 100755 index 00000000..4fbed475 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'connectivity' diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/AndroidManifest.xml new file mode 100755 index 00000000..6435d2cb --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java new file mode 100755 index 00000000..d5e5cbbd --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java @@ -0,0 +1,121 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.fluttercommunity.plus.connectivity; + +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.os.Build; +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import java.util.ArrayList; +import java.util.List; + +/** Reports connectivity related information such as connectivity type and wifi information. */ +public class Connectivity { + static final String CONNECTIVITY_NONE = "none"; + static final String CONNECTIVITY_WIFI = "wifi"; + static final String CONNECTIVITY_MOBILE = "mobile"; + static final String CONNECTIVITY_ETHERNET = "ethernet"; + static final String CONNECTIVITY_BLUETOOTH = "bluetooth"; + static final String CONNECTIVITY_VPN = "vpn"; + static final String CONNECTIVITY_OTHER = "other"; + private final ConnectivityManager connectivityManager; + + public Connectivity(ConnectivityManager connectivityManager) { + this.connectivityManager = connectivityManager; + } + + List getNetworkTypes() { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Network network = connectivityManager.getActiveNetwork(); + return getCapabilitiesFromNetwork(network); + } else { + // For legacy versions, return a single type as before or adapt similarly if multiple types + // need to be supported + return getNetworkTypesLegacy(); + } + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + List getCapabilitiesFromNetwork(Network network) { + NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network); + return getCapabilitiesList(capabilities); + } + + @NonNull + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + List getCapabilitiesList(NetworkCapabilities capabilities) { + List types = new ArrayList<>(); + if (capabilities == null + || !capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { + types.add(CONNECTIVITY_NONE); + return types; + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) + || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) { + types.add(CONNECTIVITY_WIFI); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { + types.add(CONNECTIVITY_ETHERNET); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { + types.add(CONNECTIVITY_VPN); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + types.add(CONNECTIVITY_MOBILE); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) { + types.add(CONNECTIVITY_BLUETOOTH); + } + if (types.isEmpty() + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { + types.add(CONNECTIVITY_OTHER); + } + if (types.isEmpty()) { + types.add(CONNECTIVITY_NONE); + } + return types; + } + + @SuppressWarnings("deprecation") + private List getNetworkTypesLegacy() { + // handle type for Android versions less than Android 6 + android.net.NetworkInfo info = connectivityManager.getActiveNetworkInfo(); + List types = new ArrayList<>(); + if (info == null || !info.isConnected()) { + types.add(CONNECTIVITY_NONE); + return types; + } + int type = info.getType(); + switch (type) { + case ConnectivityManager.TYPE_BLUETOOTH: + types.add(CONNECTIVITY_BLUETOOTH); + break; + case ConnectivityManager.TYPE_ETHERNET: + types.add(CONNECTIVITY_ETHERNET); + break; + case ConnectivityManager.TYPE_WIFI: + case ConnectivityManager.TYPE_WIMAX: + types.add(CONNECTIVITY_WIFI); + break; + case ConnectivityManager.TYPE_VPN: + types.add(CONNECTIVITY_VPN); + break; + case ConnectivityManager.TYPE_MOBILE: + case ConnectivityManager.TYPE_MOBILE_DUN: + case ConnectivityManager.TYPE_MOBILE_HIPRI: + types.add(CONNECTIVITY_MOBILE); + break; + default: + types.add(CONNECTIVITY_OTHER); + } + return types; + } + + public ConnectivityManager getConnectivityManager() { + return connectivityManager; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java new file mode 100755 index 00000000..324d3d23 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java @@ -0,0 +1,121 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.fluttercommunity.plus.connectivity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import io.flutter.plugin.common.EventChannel; +import java.util.List; + +/** + * The ConnectivityBroadcastReceiver receives the connectivity updates and send them to the UIThread + * through an {@link EventChannel.EventSink} + * + *

Use {@link + * io.flutter.plugin.common.EventChannel#setStreamHandler(io.flutter.plugin.common.EventChannel.StreamHandler)} + * to set up the receiver. + */ +public class ConnectivityBroadcastReceiver extends BroadcastReceiver + implements EventChannel.StreamHandler { + private final Context context; + private final Connectivity connectivity; + private EventChannel.EventSink events; + private final Handler mainHandler = new Handler(Looper.getMainLooper()); + private ConnectivityManager.NetworkCallback networkCallback; + public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + + public ConnectivityBroadcastReceiver(Context context, Connectivity connectivity) { + this.context = context; + this.connectivity = connectivity; + } + + @Override + public void onListen(Object arguments, EventChannel.EventSink events) { + this.events = events; + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + networkCallback = + new ConnectivityManager.NetworkCallback() { + @Override + public void onAvailable(Network network) { + // onAvailable is called when the phone switches to a new network + // e.g. the phone was offline and gets wifi connection + // or the phone was on wifi and now switches to mobile. + // The plugin sends the current capability connection to the users. + sendEvent(connectivity.getCapabilitiesFromNetwork(network)); + } + + @Override + public void onCapabilitiesChanged( + Network network, NetworkCapabilities networkCapabilities) { + // This callback is called multiple times after a call to onAvailable + // this also causes multiple callbacks to the Flutter layer. + sendEvent(connectivity.getCapabilitiesList(networkCapabilities)); + } + + @Override + public void onLost(Network network) { + // This callback is called when a capability is lost. + // + // The provided Network object contains information about the + // network capability that has been lost, so we cannot use it. + // + // Instead, post the current network but with a delay long enough + // that we avoid a race condition. + sendCurrentStatusWithDelay(); + } + }; + connectivity.getConnectivityManager().registerDefaultNetworkCallback(networkCallback); + } else { + context.registerReceiver(this, new IntentFilter(CONNECTIVITY_ACTION)); + } + // Need to emit first event with connectivity types without waiting for first change in system + // that might happen much later + sendEvent(connectivity.getNetworkTypes()); + } + + @Override + public void onCancel(Object arguments) { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (networkCallback != null) { + connectivity.getConnectivityManager().unregisterNetworkCallback(networkCallback); + networkCallback = null; + } + } else { + try { + context.unregisterReceiver(this); + } catch (Exception e) { + // listen never called, ignore the error + } + } + } + + @Override + public void onReceive(Context context, Intent intent) { + if (events != null) { + events.success(connectivity.getNetworkTypes()); + } + } + + private void sendEvent(List networkTypes) { + Runnable runnable = () -> events.success(networkTypes); + // Emit events on main thread + mainHandler.post(runnable); + } + + private void sendCurrentStatusWithDelay() { + Runnable runnable = () -> events.success(connectivity.getNetworkTypes()); + // Emit events on main thread + // 500 milliseconds to avoid race conditions + mainHandler.postDelayed(runnable, 500); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java new file mode 100755 index 00000000..e6cfbf1c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java @@ -0,0 +1,37 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.fluttercommunity.plus.connectivity; + +import androidx.annotation.NonNull; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; + +/** + * The handler receives {@link MethodCall}s from the UIThread, gets the related information from + * a @{@link Connectivity}, and then send the result back to the UIThread through the {@link + * MethodChannel.Result}. + */ +class ConnectivityMethodChannelHandler implements MethodChannel.MethodCallHandler { + + private final Connectivity connectivity; + + /** + * Construct the ConnectivityMethodChannelHandler with a {@code connectivity}. The {@code + * connectivity} must not be null. + */ + ConnectivityMethodChannelHandler(Connectivity connectivity) { + assert (connectivity != null); + this.connectivity = connectivity; + } + + @Override + public void onMethodCall(MethodCall call, @NonNull MethodChannel.Result result) { + if ("check".equals(call.method)) { + result.success(connectivity.getNetworkTypes()); + } else { + result.notImplemented(); + } + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java new file mode 100755 index 00000000..666cfb83 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java @@ -0,0 +1,56 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.fluttercommunity.plus.connectivity; + +import android.content.Context; +import android.net.ConnectivityManager; +import androidx.annotation.NonNull; +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.EventChannel; +import io.flutter.plugin.common.MethodChannel; + +/** ConnectivityPlugin */ +public class ConnectivityPlugin implements FlutterPlugin { + + private MethodChannel methodChannel; + private EventChannel eventChannel; + private ConnectivityBroadcastReceiver receiver; + + @Override + public void onAttachedToEngine(FlutterPluginBinding binding) { + setupChannels(binding.getBinaryMessenger(), binding.getApplicationContext()); + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + teardownChannels(); + } + + private void setupChannels(BinaryMessenger messenger, Context context) { + methodChannel = new MethodChannel(messenger, "dev.fluttercommunity.plus/connectivity"); + eventChannel = new EventChannel(messenger, "dev.fluttercommunity.plus/connectivity_status"); + ConnectivityManager connectivityManager = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + + Connectivity connectivity = new Connectivity(connectivityManager); + + ConnectivityMethodChannelHandler methodChannelHandler = + new ConnectivityMethodChannelHandler(connectivity); + receiver = new ConnectivityBroadcastReceiver(context, connectivity); + + methodChannel.setMethodCallHandler(methodChannelHandler); + eventChannel.setStreamHandler(receiver); + } + + private void teardownChannels() { + methodChannel.setMethodCallHandler(null); + eventChannel.setStreamHandler(null); + receiver.onCancel(null); + methodChannel = null; + eventChannel = null; + receiver = null; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.h new file mode 100755 index 00000000..dc6d193c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.h @@ -0,0 +1,8 @@ +#if TARGET_OS_IOS +#import +#elif TARGET_OS_OSX +#import +#endif + +@interface ConnectivityPlusPlugin : NSObject +@end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.m b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.m new file mode 100755 index 00000000..43af3800 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.m @@ -0,0 +1,15 @@ +#import "ConnectivityPlusPlugin.h" +#if __has_include() +#import +#else +// Support project import fallback if the generated compatibility header +// is not copied when this plugin is created as a library. +// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 +#import "connectivity_plus-Swift.h" +#endif + +@implementation ConnectivityPlusPlugin ++ (void)registerWithRegistrar:(NSObject *)registrar { + [SwiftConnectivityPlusPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityProvider.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityProvider.swift new file mode 100755 index 00000000..ad2cbc1e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityProvider.swift @@ -0,0 +1,21 @@ +import Foundation + +public enum ConnectivityType { + case none + case wiredEthernet + case wifi + case cellular + case other +} + +public protocol ConnectivityProvider: NSObjectProtocol { + typealias ConnectivityUpdateHandler = ([ConnectivityType]) -> Void + + var currentConnectivityTypes: [ConnectivityType] { get } + + var connectivityUpdateHandler: ConnectivityUpdateHandler? { get set } + + func start() + + func stop() +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/PathMonitorConnectivityProvider.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/PathMonitorConnectivityProvider.swift new file mode 100755 index 00000000..d7a8252b --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/PathMonitorConnectivityProvider.swift @@ -0,0 +1,69 @@ +import Foundation +import Network + +public class PathMonitorConnectivityProvider: NSObject, ConnectivityProvider { + + // Use .utility, as it is intended for tasks that the user does not track actively. + // See: https://developer.apple.com/documentation/dispatch/dispatchqos + private let queue = DispatchQueue.global(qos: .utility) + + private var pathMonitor: NWPathMonitor? + + private func connectivityFrom(path: NWPath) -> [ConnectivityType] { + var types: [ConnectivityType] = [] + + // Check for connectivity and append to types array as necessary + if path.status == .satisfied { + if path.usesInterfaceType(.wifi) { + types.append(.wifi) + } + if path.usesInterfaceType(.cellular) { + types.append(.cellular) + } + if path.usesInterfaceType(.wiredEthernet) { + types.append(.wiredEthernet) + } + if path.usesInterfaceType(.other) { + types.append(.other) + } + } + + return types.isEmpty ? [.none] : types + } + + public var currentConnectivityTypes: [ConnectivityType] { + let path = ensurePathMonitor().currentPath + return connectivityFrom(path: path) + } + + public var connectivityUpdateHandler: ConnectivityUpdateHandler? + + override init() { + super.init() + _ = ensurePathMonitor() + } + + public func start() { + _ = ensurePathMonitor() + } + + public func stop() { + pathMonitor?.cancel() + pathMonitor = nil + } + + @discardableResult + private func ensurePathMonitor() -> NWPathMonitor { + if (pathMonitor == nil) { + let pathMonitor = NWPathMonitor() + pathMonitor.start(queue: queue) + pathMonitor.pathUpdateHandler = pathUpdateHandler + self.pathMonitor = pathMonitor + } + return self.pathMonitor! + } + + private func pathUpdateHandler(path: NWPath) { + connectivityUpdateHandler?(connectivityFrom(path: path)) + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/SwiftConnectivityPlusPlugin.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/SwiftConnectivityPlusPlugin.swift new file mode 100755 index 00000000..de4ac251 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/SwiftConnectivityPlusPlugin.swift @@ -0,0 +1,101 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source is governed by a BSD-style license that can +// be found in the LICENSE file. + +#if os(iOS) +import Flutter +#elseif os(macOS) +import Cocoa +import FlutterMacOS +#endif + +public class SwiftConnectivityPlusPlugin: NSObject, FlutterPlugin, FlutterStreamHandler { + private let connectivityProvider: ConnectivityProvider + private var eventSink: FlutterEventSink? + + init(connectivityProvider: ConnectivityProvider) { + self.connectivityProvider = connectivityProvider + super.init() + self.connectivityProvider.connectivityUpdateHandler = connectivityUpdateHandler + } + + public static func register(with registrar: FlutterPluginRegistrar) { + #if os(iOS) + let binaryMessenger = registrar.messenger() + #elseif os(macOS) + let binaryMessenger = registrar.messenger + #endif + + let channel = FlutterMethodChannel( + name: "dev.fluttercommunity.plus/connectivity", + binaryMessenger: binaryMessenger) + + let streamChannel = FlutterEventChannel( + name: "dev.fluttercommunity.plus/connectivity_status", + binaryMessenger: binaryMessenger) + + let connectivityProvider = PathMonitorConnectivityProvider() + let instance = SwiftConnectivityPlusPlugin(connectivityProvider: connectivityProvider) + streamChannel.setStreamHandler(instance) + + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + eventSink = nil + connectivityProvider.stop() + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "check": + result(statusFrom(connectivityTypes: connectivityProvider.currentConnectivityTypes)) + default: + result(FlutterMethodNotImplemented) + } + } + + private func statusFrom(connectivityType: ConnectivityType) -> String { + switch connectivityType { + case .wifi: + return "wifi" + case .cellular: + return "mobile" + case .wiredEthernet: + return "ethernet" + case .other: + return "other" + case .none: + return "none" + } + } + + private func statusFrom(connectivityTypes: [ConnectivityType]) -> [String] { + return connectivityTypes.map { + self.statusFrom(connectivityType: $0) + } + } + + public func onListen( + withArguments _: Any?, + eventSink events: @escaping FlutterEventSink + ) -> FlutterError? { + eventSink = events + connectivityProvider.start() + // Update this to handle a list + connectivityUpdateHandler(connectivityTypes: connectivityProvider.currentConnectivityTypes) + return nil + } + + private func connectivityUpdateHandler(connectivityTypes: [ConnectivityType]) { + DispatchQueue.main.async { + self.eventSink?(self.statusFrom(connectivityTypes: connectivityTypes)) + } + } + + public func onCancel(withArguments _: Any?) -> FlutterError? { + connectivityProvider.stop() + eventSink = nil + return nil + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/PrivacyInfo.xcprivacy b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/PrivacyInfo.xcprivacy new file mode 100755 index 00000000..a34b7e2e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/connectivity_plus.podspec b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/connectivity_plus.podspec new file mode 100755 index 00000000..faa34ac9 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/connectivity_plus.podspec @@ -0,0 +1,30 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'connectivity_plus' + s.version = '0.0.1' + s.summary = 'Flutter Connectivity' + s.description = <<-DESC +This plugin allows Flutter apps to discover network connectivity and configure themselves accordingly. +Downloaded by pub (not CocoaPods). + DESC + s.homepage = 'https://plus.fluttercommunity.dev/' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Community Team' => 'authors@fluttercommunity.dev' } + s.source = { :http => 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/connectivity_plus' } + s.documentation_url = 'https://pub.dev/packages/connectivity_plus' + s.source_files = [ + 'Classes/**/*' + ] + s.public_header_files = [ + 'Classes/**/*.h' + ] + s.ios.dependency 'Flutter' + s.osx.dependency 'FlutterMacOS' + s.ios.deployment_target = '12.0' + s.osx.deployment_target = '10.14' + s.swift_version = '5.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.ios.resource_bundles = {'connectivity_plus_privacy' => ['PrivacyInfo.xcprivacy']} +end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/README.md new file mode 100755 index 00000000..a1356260 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/README.md @@ -0,0 +1,16 @@ +# example + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/analysis_options.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/analysis_options.yaml new file mode 100755 index 00000000..61b6c4de --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +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` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/build.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/build.gradle new file mode 100755 index 00000000..6485aa45 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/build.gradle @@ -0,0 +1,67 @@ +plugins { + id "com.android.application" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + compileSdk 34 + + namespace 'io.flutter.plugins.connectivityexample' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + applicationId "io.flutter.plugins.connectivityexample" + minSdk 21 + targetSdk 34 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test:runner:1.6.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/AndroidManifest.xml new file mode 100755 index 00000000..b55db54c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java new file mode 100755 index 00000000..0f0dcf25 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java @@ -0,0 +1,17 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.connectivityexample; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.integration_test.FlutterTestRunner; +import io.flutter.embedding.android.FlutterActivity; +import org.junit.Rule; +import org.junit.runner.RunWith; + +@RunWith(FlutterTestRunner.class) +public class FlutterActivityTest { + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100755 index 00000000..db77bb4b Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100755 index 00000000..17987b79 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100755 index 00000000..09d43914 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100755 index 00000000..d5f1c8d3 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100755 index 00000000..4d6372ee Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/build.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/build.gradle new file mode 100755 index 00000000..bc157bd1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle.properties new file mode 100755 index 00000000..94adc3a3 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..032437da --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Oct 05 14:43:11 CEST 2021 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/settings.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/settings.gradle new file mode 100755 index 00000000..5fad357a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/settings.gradle @@ -0,0 +1,24 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.3.1" apply false +} + +include ":app" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/integration_test/connectivity_plus_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/integration_test/connectivity_plus_test.dart new file mode 100755 index 00000000..fe8cd72f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/integration_test/connectivity_plus_test.dart @@ -0,0 +1,57 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'dart:io'; + +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late Connectivity connectivity; + + group('Connectivity test driver', () { + setUpAll(() async { + connectivity = Connectivity(); + }); + + testWidgets('test connectivity result', (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + expect(result, isNotNull); + }); + + testWidgets('connectivity on Android newer than 5 (API 21) should be wifi', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + + expect(result, [ConnectivityResult.wifi]); + }, + skip: !Platform.isAndroid || + Platform.operatingSystemVersion.contains('5.0.2')); + + testWidgets('connectivity on Android 5 (API 21) should be mobile', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + + expect(result, [ConnectivityResult.mobile]); + }, + skip: !Platform.isAndroid || + !Platform.operatingSystemVersion.contains('5.0.2')); + + testWidgets('connectivity on MacOS should be ethernet', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + + expect(result, [ConnectivityResult.ethernet]); + }, skip: !Platform.isMacOS); + + testWidgets('connectivity on Linux should be none', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + + expect(result, [ConnectivityResult.other]); + }, skip: !Platform.isLinux); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/AppFrameworkInfo.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100755 index 00000000..7c569640 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Debug.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Debug.xcconfig new file mode 100755 index 00000000..ec97fc6f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Release.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Release.xcconfig new file mode 100755 index 00000000..c4855bfe --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.pbxproj b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..e65736f1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,723 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + B694D755AB7FF7CFD2929C58 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1500449A12D050424A57867A /* Pods_Runner.framework */; }; + F4A8BC5E970EB9B53999ED02 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A8A7721673D9FFDF143C320 /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 1500449A12D050424A57867A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 257D002264E2484E15211C1B /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4190CA09B8971D8AA0EC8FB9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 5A8A7721673D9FFDF143C320 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + AA3CF93A0B4C03146682AA3A /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + B32C00FEDA2DE2C44D23000B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + CC3B43C8CED1D022483DD294 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + F95E3B38B7E77717BBBD1F33 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1DAEBA9DF8F9603938D62C8C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F4A8BC5E970EB9B53999ED02 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B694D755AB7FF7CFD2929C58 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 4D0D1BE63803AD280C576750 /* Pods */ = { + isa = PBXGroup; + children = ( + 4190CA09B8971D8AA0EC8FB9 /* Pods-Runner.debug.xcconfig */, + 257D002264E2484E15211C1B /* Pods-Runner.release.xcconfig */, + B32C00FEDA2DE2C44D23000B /* Pods-Runner.profile.xcconfig */, + F95E3B38B7E77717BBBD1F33 /* Pods-RunnerTests.debug.xcconfig */, + CC3B43C8CED1D022483DD294 /* Pods-RunnerTests.release.xcconfig */, + AA3CF93A0B4C03146682AA3A /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + 4D0D1BE63803AD280C576750 /* Pods */, + F017D9A85219F51EE7853CBE /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + F017D9A85219F51EE7853CBE /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1500449A12D050424A57867A /* Pods_Runner.framework */, + 5A8A7721673D9FFDF143C320 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 578B235B4B01D5488E7B29F4 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 1DAEBA9DF8F9603938D62C8C /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + F3922377736DD5E91A9CE1B1 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + CAF18DED242B2DB037C2D3CE /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 578B235B4B01D5488E7B29F4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + CAF18DED242B2DB037C2D3CE /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F3922377736DD5E91A9CE1B1 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F95E3B38B7E77717BBBD1F33 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CC3B43C8CED1D022483DD294 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AA3CF93A0B4C03146682AA3A /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..919434a6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..8e3ca5df --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/AppDelegate.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/AppDelegate.swift new file mode 100755 index 00000000..70693e4a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..d36b1fab --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100755 index 00000000..dc9ada47 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100755 index 00000000..7353c41e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100755 index 00000000..6ed2d933 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100755 index 00000000..4cd7b009 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100755 index 00000000..fe730945 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100755 index 00000000..321773cd Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100755 index 00000000..502f463a Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100755 index 00000000..e9f5fea2 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100755 index 00000000..84ac32ae Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100755 index 00000000..8953cba0 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100755 index 00000000..0467bf12 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100755 index 00000000..0bedcf2f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100755 index 00000000..89c2725b --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 00000000..f2e259c7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/Main.storyboard b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100755 index 00000000..f3c28516 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Info.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Info.plist new file mode 100755 index 00000000..5069379d --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Connectivity Plus Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + connectivity_plus_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Runner-Bridging-Header.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Runner-Bridging-Header.h new file mode 100755 index 00000000..308a2a56 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/RunnerTests/RunnerTests.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..86a7c3b1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/lib/main.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/lib/main.dart new file mode 100755 index 00000000..29927da5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/lib/main.dart @@ -0,0 +1,125 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'dart:developer' as developer; + +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + useMaterial3: true, + colorSchemeSeed: const Color(0x9f4376f8), + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, required this.title}) : super(key: key); + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + List _connectionStatus = [ConnectivityResult.none]; + final Connectivity _connectivity = Connectivity(); + late StreamSubscription> _connectivitySubscription; + + @override + void initState() { + super.initState(); + initConnectivity(); + + _connectivitySubscription = + _connectivity.onConnectivityChanged.listen(_updateConnectionStatus); + } + + @override + void dispose() { + _connectivitySubscription.cancel(); + super.dispose(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future initConnectivity() async { + late List result; + // Platform messages may fail, so we use a try/catch PlatformException. + try { + result = await _connectivity.checkConnectivity(); + } on PlatformException catch (e) { + developer.log('Couldn\'t check connectivity status', error: e); + return; + } + + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) { + return Future.value(null); + } + + return _updateConnectionStatus(result); + } + + Future _updateConnectionStatus(List result) async { + setState(() { + _connectionStatus = result; + }); + // ignore: avoid_print + print('Connectivity changed: $_connectionStatus'); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Connectivity Plus Example'), + elevation: 4, + ), + body: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Spacer(flex: 2), + Text( + 'Active connection types:', + style: Theme.of(context).textTheme.headlineMedium, + ), + const Spacer(), + ListView( + shrinkWrap: true, + children: List.generate( + _connectionStatus.length, + (index) => Center( + child: Text( + _connectionStatus[index].toString(), + style: Theme.of(context).textTheme.headlineSmall, + ), + )), + ), + const Spacer(flex: 2), + ], + ), + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/CMakeLists.txt new file mode 100755 index 00000000..279007eb --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "io.flutter.plugins.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..5b465c7e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/main.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/main.cc new file mode 100755 index 00000000..8bc15615 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/main.cc @@ -0,0 +1,11 @@ +#include "my_application.h" + +int main(int argc, char **argv) { + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); + + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.cc new file mode 100755 index 00000000..cef2f771 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.cc @@ -0,0 +1,45 @@ +#include "my_application.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication *application) { + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +static void my_application_class_init(MyApplicationClass *klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; +} + +static void my_application_init(MyApplication *self) {} + +MyApplication *my_application_new() { + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.h new file mode 100755 index 00000000..3258a73c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication *my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Debug.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100755 index 00000000..4b81f9b2 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Release.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100755 index 00000000..5caa9d15 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.pbxproj b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..eab0503a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,791 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 516D2749BEC98FB8007BDD39 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5680711160F3554DA073A4A /* Pods_Runner.framework */; }; + A0DE1A8BAD92B1FC97AF3072 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7DE3F356208F8AF32BF63FB /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2DA90B2343051DD978570433 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 32DD3AA8862D40CEC34F4823 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* connectivity_plus_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_device_info.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 818BD3063832BFCCEB86E2DC /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 849CE1B58CE95AE709338025 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + A5680711160F3554DA073A4A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A7DE3F356208F8AF32BF63FB /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BC7DC07E4588932BDF542A1C /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + F074D7F65F9EE14BDF366DEA /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A0DE1A8BAD92B1FC97AF3072 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 516D2749BEC98FB8007BDD39 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 7C46BB738D7DFC62A80734E0 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* example_device_info.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + 7C46BB738D7DFC62A80734E0 /* Pods */ = { + isa = PBXGroup; + children = ( + 849CE1B58CE95AE709338025 /* Pods-Runner.debug.xcconfig */, + F074D7F65F9EE14BDF366DEA /* Pods-Runner.release.xcconfig */, + 32DD3AA8862D40CEC34F4823 /* Pods-Runner.profile.xcconfig */, + BC7DC07E4588932BDF542A1C /* Pods-RunnerTests.debug.xcconfig */, + 2DA90B2343051DD978570433 /* Pods-RunnerTests.release.xcconfig */, + 818BD3063832BFCCEB86E2DC /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A5680711160F3554DA073A4A /* Pods_Runner.framework */, + A7DE3F356208F8AF32BF63FB /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + E6B78D17FAAB2457BAC2FC37 /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 290ED1BDB70728341B0EE329 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 9130A189025A19331F12A8D2 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* example_device_info.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 290ED1BDB70728341B0EE329 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 9130A189025A19331F12A8D2 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E6B78D17FAAB2457BAC2FC37 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC7DC07E4588932BDF542A1C /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/connectivity_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/connectivity_plus_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2DA90B2343051DD978570433 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/connectivity_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/connectivity_plus_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 818BD3063832BFCCEB86E2DC /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/connectivity_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/connectivity_plus_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..fa25347e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/AppDelegate.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/AppDelegate.swift new file mode 100755 index 00000000..d53ef643 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..a2ec33f1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "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" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100755 index 00000000..82b6f9d9 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100755 index 00000000..13b35eba Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100755 index 00000000..0a3f5fa4 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100755 index 00000000..bdb57226 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100755 index 00000000..f083318e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100755 index 00000000..326c0e72 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100755 index 00000000..2f1632cf Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Base.lproj/MainMenu.xib b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100755 index 00000000..80e867a4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/AppInfo.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100755 index 00000000..516d9adf --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = connectivity_plus_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlus.example + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 io.flutter.plugins. All rights reserved. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Debug.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Debug.xcconfig new file mode 100755 index 00000000..36b0fd94 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Release.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Release.xcconfig new file mode 100755 index 00000000..dff4f495 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Warnings.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100755 index 00000000..42bcbf47 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/DebugProfile.entitlements b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/DebugProfile.entitlements new file mode 100755 index 00000000..dddb8a30 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Info.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Info.plist new file mode 100755 index 00000000..4789daa6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/MainFlutterWindow.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/MainFlutterWindow.swift new file mode 100755 index 00000000..3cc05eb2 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Release.entitlements b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Release.entitlements new file mode 100755 index 00000000..852fa1a4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/RunnerTests/RunnerTests.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..5418c9f5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/pubspec.yaml new file mode 100755 index 00000000..64fc0b64 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/pubspec.yaml @@ -0,0 +1,23 @@ +name: connectivity_plus_example +description: Demonstrates how to use the connectivity_plus plugin. + +environment: + sdk: '>=2.12.0 <4.0.0' + +dependencies: + flutter: + sdk: flutter + connectivity_plus: ^6.0.5 + +dev_dependencies: + flutter_driver: + sdk: flutter + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + test: ^1.16.4 + flutter_lints: ^4.0.0 + +flutter: + uses-material-design: true diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/favicon.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/favicon.png new file mode 100755 index 00000000..8aaa46ac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/favicon.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-192.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-192.png new file mode 100755 index 00000000..b749bfef Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-192.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-512.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-512.png new file mode 100755 index 00000000..88cfd48d Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-512.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-192.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-192.png new file mode 100755 index 00000000..eb9b4d76 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-192.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-512.png b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-512.png new file mode 100755 index 00000000..d69c5669 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-512.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/index.html b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/index.html new file mode 100755 index 00000000..9b7a438f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/manifest.json b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/manifest.json new file mode 100755 index 00000000..8c012917 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/CMakeLists.txt new file mode 100755 index 00000000..abf90408 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.15) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..b02c5485 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..977e38b5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/Runner.rc b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/Runner.rc new file mode 100755 index 00000000..f414c2d8 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "io.flutter.plugins" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 io.flutter.plugins. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..0f0105d9 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.cpp @@ -0,0 +1,64 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opporutunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..69234d4f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.h @@ -0,0 +1,39 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "run_loop.h" +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { +public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + virtual ~FlutterWindow(); + +protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + +private: + // The run loop driving events for this window. + RunLoop *run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/main.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/main.cpp new file mode 100755 index 00000000..09895686 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/main.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resource.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resources/app_icon.ico b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resources/app_icon.ico differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.cpp new file mode 100755 index 00000000..31b89f62 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.cpp @@ -0,0 +1,66 @@ +#include "run_loop.h" + +#include + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto instance : flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.h new file mode 100755 index 00000000..7fe1aacc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.h @@ -0,0 +1,38 @@ +#ifndef RUNNER_RUN_LOOP_H_ +#define RUNNER_RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { +public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const &) = delete; + RunLoop &operator=(RunLoop const &) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + +private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUNNER_RUN_LOOP_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/runner.exe.manifest b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.cpp new file mode 100755 index 00000000..7758aabf --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.cpp @@ -0,0 +1,63 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t *utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.h new file mode 100755 index 00000000..ff43ce2c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t *utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..90ff01e5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.cpp @@ -0,0 +1,237 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { +public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + +private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar *instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; + +const wchar_t *WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size) { + Destroy(); + + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window *that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.h new file mode 100755 index 00000000..7b518125 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.h @@ -0,0 +1,95 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { +public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/connectivity_plus.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/connectivity_plus.dart new file mode 100755 index 00000000..cef5ddee --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/connectivity_plus.dart @@ -0,0 +1,66 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:collection/collection.dart'; + +// Export enums from the platform_interface so plugin users can use them directly. +export 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart' + show ConnectivityResult; + +export 'src/connectivity_plus_linux.dart' + if (dart.library.js_interop) 'src/connectivity_plus_web.dart'; + +/// Discover network connectivity configurations: Distinguish between WI-FI and cellular, check WI-FI status and more. +class Connectivity { + /// Constructs a singleton instance of [Connectivity]. + /// + /// [Connectivity] is designed to work as a singleton. + // When a second instance is created, the first instance will not be able to listen to the + // EventChannel because it is overridden. Forcing the class to be a singleton class can prevent + // misuse of creating a second instance from a programmer. + factory Connectivity() { + _singleton ??= Connectivity._(); + return _singleton!; + } + + Connectivity._(); + + static Connectivity? _singleton; + + static ConnectivityPlatform get _platform { + return ConnectivityPlatform.instance; + } + + /// Exposes connectivity update events from the platform. + /// + /// On iOS, the connectivity status might not update when WiFi + /// status changes, this is a known issue that only affects simulators. + /// For details see https://github.com/fluttercommunity/plus_plugins/issues/479. + /// + /// The emitted list is never empty. In case of no connectivity, the list contains + /// a single element of [ConnectivityResult.none]. Note also that this is the only + /// case where [ConnectivityResult.none] is present. + /// + /// This method applies [Stream.distinct] over the received events to ensure + /// only emiting when connectivity changes. + Stream> get onConnectivityChanged { + return _platform.onConnectivityChanged.distinct((a, b) => a.equals(b)); + } + + /// Checks the connection status of the device. + /// + /// Do not use the result of this function to decide whether you can reliably + /// make a network request, it only gives you the radio status. Instead, listen + /// for connectivity changes via [onConnectivityChanged] stream. + /// + /// The returned list is never empty. In case of no connectivity, the list contains + /// a single element of [ConnectivityResult.none]. Note also that this is the only + /// case where [ConnectivityResult.none] is present. + Future> checkConnectivity() { + return _platform.checkConnectivity(); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_linux.dart new file mode 100755 index 00000000..31b562aa --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_linux.dart @@ -0,0 +1,94 @@ +import 'dart:async'; + +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:meta/meta.dart'; +import 'package:nm/nm.dart'; + +// Used internally +// ignore_for_file: public_member_api_docs + +@visibleForTesting +typedef NetworkManagerClientFactory = NetworkManagerClient Function(); + +/// The Linux implementation of ConnectivityPlatform. +class ConnectivityPlusLinuxPlugin extends ConnectivityPlatform { + /// Register this dart class as the platform implementation for linux + static void registerWith() { + ConnectivityPlatform.instance = ConnectivityPlusLinuxPlugin(); + } + + /// Checks the connection status of the device. + @override + Future> checkConnectivity() async { + final client = createClient(); + await client.connect(); + final connectivity = _getConnectivity(client); + await client.close(); + return connectivity; + } + + NetworkManagerClient? _client; + StreamController>? _controller; + + /// Returns a Stream of ConnectivityResults changes. + @override + Stream> get onConnectivityChanged { + _controller ??= StreamController>.broadcast( + onListen: _startListenConnectivity, + onCancel: _stopListenConnectivity, + ); + return _controller!.stream; + } + + List _getConnectivity(NetworkManagerClient client) { + final List results = []; + if (client.connectivity == NetworkManagerConnectivityState.none) { + results.add(ConnectivityResult.none); + } else { + if (client.primaryConnectionType.contains('wireless')) { + results.add(ConnectivityResult.wifi); + } + if (client.primaryConnectionType.contains('ethernet')) { + results.add(ConnectivityResult.ethernet); + } + if (client.primaryConnectionType.contains('vpn')) { + results.add(ConnectivityResult.vpn); + } + if (client.primaryConnectionType.contains('bluetooth')) { + results.add(ConnectivityResult.bluetooth); + } + if (client.primaryConnectionType.contains('mobile')) { + results.add(ConnectivityResult.mobile); + } + // Assuming 'other' is a catch-all for unspecified types + if (results.isEmpty) { + results.add(ConnectivityResult.other); + } + } + return results; + } + + Future _startListenConnectivity() async { + _client ??= createClient(); + await _client!.connect(); + _addConnectivity(_client!); + _client!.propertiesChanged.listen((properties) { + if (properties.contains('Connectivity')) { + _addConnectivity(_client!); + } + }); + } + + void _addConnectivity(NetworkManagerClient client) { + _controller!.add(_getConnectivity(client)); + } + + Future _stopListenConnectivity() async { + await _client?.close(); + _client = null; + } + + @visibleForTesting + // ignore: prefer_function_declarations_over_variables + NetworkManagerClientFactory createClient = () => NetworkManagerClient(); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_web.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_web.dart new file mode 100755 index 00000000..d2f35d5d --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_web.dart @@ -0,0 +1,13 @@ +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +import 'web/dart_html_connectivity_plugin.dart'; + +/// The web implementation of the ConnectivityPlatform of the Connectivity plugin. +class ConnectivityPlusWebPlugin extends ConnectivityPlatform { + /// Factory method that initializes the connectivity plugin platform with an instance + /// of the plugin for the web. + static void registerWith(Registrar registrar) { + ConnectivityPlatform.instance = DartHtmlConnectivityPlugin(); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/dart_html_connectivity_plugin.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/dart_html_connectivity_plugin.dart new file mode 100755 index 00000000..0ad59a6d --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/dart_html_connectivity_plugin.dart @@ -0,0 +1,35 @@ +import 'dart:async'; +import 'package:web/web.dart'; + +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; + +import '../connectivity_plus_web.dart'; + +/// The web implementation of the ConnectivityPlatform of the Connectivity plugin. +class DartHtmlConnectivityPlugin extends ConnectivityPlusWebPlugin { + /// Checks the connection status of the device. + @override + Future> checkConnectivity() async { + return (window.navigator.onLine) + ? [ConnectivityResult.wifi] + : [ConnectivityResult.none]; + } + + StreamController>? _connectivityResult; + + /// Returns a Stream of ConnectivityResults changes. + @override + Stream> get onConnectivityChanged { + if (_connectivityResult == null) { + _connectivityResult = + StreamController>.broadcast(); + const EventStreamProvider('online').forTarget(window).listen((_) { + _connectivityResult!.add([ConnectivityResult.wifi]); + }); + const EventStreamProvider('offline').forTarget(window).listen((_) { + _connectivityResult!.add([ConnectivityResult.none]); + }); + } + return _connectivityResult!.stream; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/utils/connectivity_result.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/utils/connectivity_result.dart new file mode 100755 index 00000000..c3250f19 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/utils/connectivity_result.dart @@ -0,0 +1,58 @@ +import 'dart:html' as html show NetworkInformation; + +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; + +/// Converts an incoming NetworkInformation object into the correct ConnectivityResult. +List networkInformationToConnectivityResult( + html.NetworkInformation info, +) { + if (info.downlink == 0 && info.rtt == 0) { + return [ConnectivityResult.none]; + } + if (info.type != null) { + return _typeToConnectivityResult(info.type!); + } + if (info.effectiveType != null) { + return _effectiveTypeToConnectivityResult(info.effectiveType!); + } + return [ConnectivityResult.none]; +} + +List _effectiveTypeToConnectivityResult( + String effectiveType) { + // Possible values: + /*'2g'|'3g'|'4g'|'slow-2g'*/ + switch (effectiveType) { + case 'slow-2g': + case '2g': + case '3g': + case '4g': + return [ConnectivityResult.mobile]; + default: + return [ConnectivityResult.wifi]; + } +} + +List _typeToConnectivityResult(String type) { + // Possible values: 'bluetooth', 'cellular', 'ethernet', 'mixed', 'none', 'other', 'unknown', 'wifi', 'wimax' + switch (type) { + case 'none': + // Corrected to return a list + return [ConnectivityResult.none]; + case 'bluetooth': + return [ConnectivityResult.bluetooth]; + case 'cellular': + case 'mixed': + case 'other': + case 'unknown': + return [ConnectivityResult.mobile]; + case 'ethernet': + return [ConnectivityResult.ethernet]; + case 'wifi': + case 'wimax': // Assuming 'wimax' should be treated the same as 'wifi' + return [ConnectivityResult.wifi]; + default: + // Assuming default should be 'other' to cover all unspecified cases + return [ConnectivityResult.other]; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/pubspec.yaml new file mode 100755 index 00000000..66956fff --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/pubspec.yaml @@ -0,0 +1,57 @@ +name: connectivity_plus +description: Flutter plugin for discovering the state of the network (WiFi & mobile/cellular) connectivity on Android and iOS. +version: 6.0.5 +homepage: https://github.com/fluttercommunity/plus_plugins +repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/connectivity_plus/connectivity_plus +issue_tracker: https://github.com/fluttercommunity/plus_plugins/labels/connectivity_plus +topics: + - connectivity + - utils + +environment: + sdk: ">=3.2.0 <4.0.0" + # Flutter versions prior to 3.7 did not support the + # sharedDarwinSource option. + flutter: ">=3.7.0" + +flutter: + plugin: + platforms: + android: + package: dev.fluttercommunity.plus.connectivity + pluginClass: ConnectivityPlugin + ios: + pluginClass: ConnectivityPlusPlugin + sharedDarwinSource: true + + linux: + dartPluginClass: ConnectivityPlusLinuxPlugin + macos: + pluginClass: ConnectivityPlusPlugin + sharedDarwinSource: true + web: + pluginClass: ConnectivityPlusWebPlugin + fileName: src/connectivity_plus_web.dart + windows: + pluginClass: ConnectivityPlusWindowsPlugin + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + connectivity_plus_platform_interface: ^2.0.1 + web: ">=0.5.0 <2.0.0" + meta: ^1.8.0 + nm: ^0.5.0 + collection: ^1.18.0 + +dev_dependencies: + flutter_test: + sdk: flutter + build_runner: ^2.3.3 + dbus: ^0.7.8 + flutter_lints: ^4.0.0 + mockito: ^5.4.0 + plugin_platform_interface: ^2.1.5 + test: ^1.22.0 diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.dart new file mode 100755 index 00000000..b7ecf03c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.dart @@ -0,0 +1,125 @@ +import 'package:connectivity_plus/src/connectivity_plus_linux.dart'; +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:nm/nm.dart'; + +import 'connectivity_plus_linux_test.mocks.dart'; + +@GenerateMocks([NetworkManagerClient]) +void main() { + test('registered instance', () { + ConnectivityPlusLinuxPlugin.registerWith(); + expect(ConnectivityPlatform.instance, isA()); + }); + + test('bluetooth', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('bluetooth'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.bluetooth])), + ); + }); + + test('ethernet', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('ethernet'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.ethernet])), + ); + }); + + test('wireless', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('wireless'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.wifi])), + ); + }); + + test('vpn', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('vpn'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.vpn])), + ); + }); + + test('wireless+vpn', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('wireless,vpn'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.wifi, ConnectivityResult.vpn])), + ); + }); + + test('no connectivity', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.none); + return client; + }; + expect(linux.checkConnectivity(), + completion(equals([ConnectivityResult.none]))); + }); + + test('connectivity changes', () { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('wireless'); + when(client.propertiesChanged).thenAnswer((_) { + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.none); + return Stream.value(['Connectivity']); + }); + return client; + }; + expect( + linux.onConnectivityChanged, + emitsInOrder([ + [ConnectivityResult.wifi], + [ConnectivityResult.none] + ])); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart new file mode 100755 index 00000000..9e1ffbcf --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart @@ -0,0 +1,205 @@ +// Mocks generated by Mockito 5.2.0 from annotations +// in connectivity_plus_linux/test/connectivity_plus_linux_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i3; + +import 'package:dbus/dbus.dart' as _i4; +import 'package:mockito/mockito.dart' as _i1; +import 'package:nm/src/network_manager_client.dart' as _i2; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types + +class _FakeNetworkManagerSettings_0 extends _i1.Fake + implements _i2.NetworkManagerSettings {} + +class _FakeNetworkManagerDnsManager_1 extends _i1.Fake + implements _i2.NetworkManagerDnsManager {} + +class _FakeNetworkManagerActiveConnection_2 extends _i1.Fake + implements _i2.NetworkManagerActiveConnection {} + +/// A class which mocks [NetworkManagerClient]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockNetworkManagerClient extends _i1.Mock + implements _i2.NetworkManagerClient { + MockNetworkManagerClient() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Stream<_i2.NetworkManagerDevice> get deviceAdded => + (super.noSuchMethod(Invocation.getter(#deviceAdded), + returnValue: Stream<_i2.NetworkManagerDevice>.empty()) + as _i3.Stream<_i2.NetworkManagerDevice>); + @override + _i3.Stream<_i2.NetworkManagerDevice> get deviceRemoved => + (super.noSuchMethod(Invocation.getter(#deviceRemoved), + returnValue: Stream<_i2.NetworkManagerDevice>.empty()) + as _i3.Stream<_i2.NetworkManagerDevice>); + @override + _i3.Stream<_i2.NetworkManagerActiveConnection> get activeConnectionAdded => + (super.noSuchMethod(Invocation.getter(#activeConnectionAdded), + returnValue: Stream<_i2.NetworkManagerActiveConnection>.empty()) + as _i3.Stream<_i2.NetworkManagerActiveConnection>); + @override + _i3.Stream<_i2.NetworkManagerActiveConnection> get activeConnectionRemoved => + (super.noSuchMethod(Invocation.getter(#activeConnectionRemoved), + returnValue: Stream<_i2.NetworkManagerActiveConnection>.empty()) + as _i3.Stream<_i2.NetworkManagerActiveConnection>); + @override + _i3.Stream> get propertiesChanged => (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: Stream>.empty()) as _i3.Stream>); + @override + List<_i2.NetworkManagerDevice> get devices => + (super.noSuchMethod(Invocation.getter(#devices), + returnValue: <_i2.NetworkManagerDevice>[]) + as List<_i2.NetworkManagerDevice>); + @override + List<_i2.NetworkManagerDevice> get allDevices => + (super.noSuchMethod(Invocation.getter(#allDevices), + returnValue: <_i2.NetworkManagerDevice>[]) + as List<_i2.NetworkManagerDevice>); + @override + bool get networkingEnabled => + (super.noSuchMethod(Invocation.getter(#networkingEnabled), + returnValue: false) as bool); + @override + bool get wirelessEnabled => (super + .noSuchMethod(Invocation.getter(#wirelessEnabled), returnValue: false) + as bool); + @override + bool get wirelessHardwareEnabled => + (super.noSuchMethod(Invocation.getter(#wirelessHardwareEnabled), + returnValue: false) as bool); + @override + bool get wwanEnabled => + (super.noSuchMethod(Invocation.getter(#wwanEnabled), returnValue: false) + as bool); + @override + bool get wwanHardwareEnabled => + (super.noSuchMethod(Invocation.getter(#wwanHardwareEnabled), + returnValue: false) as bool); + @override + List<_i2.NetworkManagerActiveConnection> get activeConnections => + (super.noSuchMethod(Invocation.getter(#activeConnections), + returnValue: <_i2.NetworkManagerActiveConnection>[]) + as List<_i2.NetworkManagerActiveConnection>); + @override + String get primaryConnectionType => + (super.noSuchMethod(Invocation.getter(#primaryConnectionType), + returnValue: '') as String); + @override + _i2.NetworkManagerMetered get metered => + (super.noSuchMethod(Invocation.getter(#metered), + returnValue: _i2.NetworkManagerMetered.unknown) + as _i2.NetworkManagerMetered); + @override + bool get startup => + (super.noSuchMethod(Invocation.getter(#startup), returnValue: false) + as bool); + @override + String get version => + (super.noSuchMethod(Invocation.getter(#version), returnValue: '') + as String); + @override + _i2.NetworkManagerConnectivityState get connectivity => + (super.noSuchMethod(Invocation.getter(#connectivity), + returnValue: _i2.NetworkManagerConnectivityState.unknown) + as _i2.NetworkManagerConnectivityState); + @override + bool get connectivityCheckAvailable => + (super.noSuchMethod(Invocation.getter(#connectivityCheckAvailable), + returnValue: false) as bool); + @override + bool get connectivityCheckEnabled => + (super.noSuchMethod(Invocation.getter(#connectivityCheckEnabled), + returnValue: false) as bool); + @override + String get connectivityCheckUri => + (super.noSuchMethod(Invocation.getter(#connectivityCheckUri), + returnValue: '') as String); + @override + _i2.NetworkManagerState get state => (super.noSuchMethod( + Invocation.getter(#state), + returnValue: _i2.NetworkManagerState.unknown) as _i2.NetworkManagerState); + @override + _i2.NetworkManagerSettings get settings => + (super.noSuchMethod(Invocation.getter(#settings), + returnValue: _FakeNetworkManagerSettings_0()) + as _i2.NetworkManagerSettings); + @override + _i2.NetworkManagerDnsManager get dnsManager => + (super.noSuchMethod(Invocation.getter(#dnsManager), + returnValue: _FakeNetworkManagerDnsManager_1()) + as _i2.NetworkManagerDnsManager); + @override + _i3.Future connect() => + (super.noSuchMethod(Invocation.method(#connect, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future setWirelessEnabled(bool? value) => + (super.noSuchMethod(Invocation.method(#setWirelessEnabled, [value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future setWwanEnabled(bool? value) => + (super.noSuchMethod(Invocation.method(#setWwanEnabled, [value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future setConnectivityCheckEnabled(bool? value) => (super + .noSuchMethod(Invocation.method(#setConnectivityCheckEnabled, [value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future<_i2.NetworkManagerActiveConnection> addAndActivateConnection( + {Map>? connection = const {}, + _i2.NetworkManagerDevice? device, + _i2.NetworkManagerAccessPoint? accessPoint}) => + (super.noSuchMethod( + Invocation.method(#addAndActivateConnection, [], { + #connection: connection, + #device: device, + #accessPoint: accessPoint + }), + returnValue: Future<_i2.NetworkManagerActiveConnection>.value( + _FakeNetworkManagerActiveConnection_2())) + as _i3.Future<_i2.NetworkManagerActiveConnection>); + @override + _i3.Future<_i2.NetworkManagerActiveConnection> activateConnection( + {_i2.NetworkManagerDevice? device, + _i2.NetworkManagerSettingsConnection? connection, + _i2.NetworkManagerAccessPoint? accessPoint}) => + (super.noSuchMethod( + Invocation.method(#activateConnection, [], { + #device: device, + #connection: connection, + #accessPoint: accessPoint + }), + returnValue: Future<_i2.NetworkManagerActiveConnection>.value( + _FakeNetworkManagerActiveConnection_2())) + as _i3.Future<_i2.NetworkManagerActiveConnection>); + @override + _i3.Future deactivateConnection( + _i2.NetworkManagerActiveConnection? connection) => + (super.noSuchMethod( + Invocation.method(#deactivateConnection, [connection]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future close() => (super.noSuchMethod(Invocation.method(#close, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_test.dart new file mode 100755 index 00000000..4f177c0f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_test.dart @@ -0,0 +1,39 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +import 'package:mockito/mockito.dart'; + +const List kCheckConnectivityResult = [ + ConnectivityResult.wifi +]; + +void main() { + group('Connectivity', () { + late Connectivity connectivity; + MockConnectivityPlatform fakePlatform; + setUp(() async { + fakePlatform = MockConnectivityPlatform(); + ConnectivityPlatform.instance = fakePlatform; + connectivity = Connectivity(); + }); + + test('checkConnectivity', () async { + final result = await connectivity.checkConnectivity(); + expect(result, kCheckConnectivityResult); + }); + }); +} + +class MockConnectivityPlatform extends Mock + with MockPlatformInterfaceMixin + implements ConnectivityPlatform { + @override + Future> checkConnectivity() async { + return kCheckConnectivityResult; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/CMakeLists.txt new file mode 100755 index 00000000..ac315ccd --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.15) +set(PROJECT_NAME "connectivity_plus") +project(${PROJECT_NAME} LANGUAGES CXX) + +# This value is used when generating builds using this plugin, so it must +# not be changed +set(PLUGIN_NAME "connectivity_plus_plugin") + +add_library(${PLUGIN_NAME} SHARED + "connectivity_plus_plugin.cpp" + "network_manager.cpp" +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE + flutter + flutter_wrapper_plugin + iphlpapi +) + +# List of absolute paths to libraries that should be bundled with the plugin +set(connectivity_plus_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/connectivity_plus_plugin.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/connectivity_plus_plugin.cpp new file mode 100755 index 00000000..cb6ae1f9 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/connectivity_plus_plugin.cpp @@ -0,0 +1,189 @@ +// clang-format off +#include "include/connectivity_plus/network_manager.h" +// clang-format on +#include "include/connectivity_plus/connectivity_plus_windows_plugin.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace { + +typedef flutter::EventChannel FlEventChannel; +typedef flutter::EventSink FlEventSink; +typedef flutter::MethodCall FlMethodCall; +typedef flutter::MethodResult FlMethodResult; +typedef flutter::MethodChannel FlMethodChannel; +typedef flutter::StreamHandler FlStreamHandler; +typedef flutter::StreamHandlerError + FlStreamHandlerError; + +class ConnectivityPlusWindowsPlugin : public flutter::Plugin { +public: + ConnectivityPlusWindowsPlugin(); + virtual ~ConnectivityPlusWindowsPlugin(); + + std::shared_ptr GetManager() const; + + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + +private: + void HandleMethodCall(const FlMethodCall &method_call, + std::unique_ptr result); + + std::shared_ptr manager; +}; + +class ConnectivityStreamHandler : public FlStreamHandler { +public: + ConnectivityStreamHandler(std::shared_ptr manager); + virtual ~ConnectivityStreamHandler(); + +protected: + void AddConnectivityEvent(); + + std::unique_ptr + OnListenInternal(const flutter::EncodableValue *arguments, + std::unique_ptr &&sink) override; + + std::unique_ptr + OnCancelInternal(const flutter::EncodableValue *arguments) override; + +private: + std::shared_ptr manager; + std::unique_ptr sink; +}; + +ConnectivityPlusWindowsPlugin::ConnectivityPlusWindowsPlugin() { + manager = std::make_shared(); + manager->Init(); +} + +ConnectivityPlusWindowsPlugin::~ConnectivityPlusWindowsPlugin() { + manager->Cleanup(); +} + +std::shared_ptr +ConnectivityPlusWindowsPlugin::GetManager() const { + return manager; +} + +void ConnectivityPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar) { + auto plugin = std::make_unique(); + + auto methodChannel = + std::make_unique>( + registrar->messenger(), "dev.fluttercommunity.plus/connectivity", + &flutter::StandardMethodCodec::GetInstance()); + + methodChannel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto &call, auto result) { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); + + auto eventChannel = std::make_unique( + registrar->messenger(), "dev.fluttercommunity.plus/connectivity_status", + &flutter::StandardMethodCodec::GetInstance()); + + eventChannel->SetStreamHandler( + std::make_unique(plugin->GetManager())); + + registrar->AddPlugin(std::move(plugin)); +} + +static std::string ConnectivityToString(ConnectivityType connectivityType) { + switch (connectivityType) { + case ConnectivityType::WiFi: + return "wifi"; + case ConnectivityType::Ethernet: + return "ethernet"; + case ConnectivityType::VPN: + return "vpn"; + case ConnectivityType::Other: + return "other"; + case ConnectivityType::None: + default: + return "none"; + } +} + +static flutter::EncodableList +EncodeConnectivityTypes(std::set connectivityTypes) { + flutter::EncodableList encodedList; + + if (connectivityTypes.empty()) { + encodedList.push_back( + flutter::EncodableValue(ConnectivityToString(ConnectivityType::None))); + return encodedList; + } + + for (const auto &type : connectivityTypes) { + std::string connectivityString = ConnectivityToString(type); + encodedList.push_back(flutter::EncodableValue(connectivityString)); + } + + return encodedList; +} + +void ConnectivityPlusWindowsPlugin::HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr> result) { + if (method_call.method_name().compare("check") == 0) { + result->Success(EncodeConnectivityTypes(manager->GetConnectivityTypes())); + } else { + result->NotImplemented(); + } +} + +ConnectivityStreamHandler::ConnectivityStreamHandler( + std::shared_ptr manager) + : manager(manager) {} + +ConnectivityStreamHandler::~ConnectivityStreamHandler() {} + +void ConnectivityStreamHandler::AddConnectivityEvent() { + sink->Success(EncodeConnectivityTypes(manager->GetConnectivityTypes())); +} + +std::unique_ptr +ConnectivityStreamHandler::OnListenInternal( + const flutter::EncodableValue *arguments, + std::unique_ptr &&events) { + sink = std::move(events); + + auto callback = + std::bind(&ConnectivityStreamHandler::AddConnectivityEvent, this); + + if (!manager->StartListen(callback)) { + return std::make_unique( + std::to_string(manager->GetError()), "NetworkManager::StartListen", + nullptr); + } + + AddConnectivityEvent(); + return nullptr; +} + +std::unique_ptr +ConnectivityStreamHandler::OnCancelInternal( + const flutter::EncodableValue *arguments) { + manager->StopListen(); + sink.reset(); + return nullptr; +} + +} // namespace + +void ConnectivityPlusWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + ConnectivityPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h new file mode 100755 index 00000000..17af4474 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h @@ -0,0 +1,23 @@ +#ifndef FLUTTER_PLUGIN_CONNECTIVITY_WINDOWS_PLUS_PLUGIN_H_ +#define FLUTTER_PLUGIN_CONNECTIVITY_WINDOWS_PLUS_PLUGIN_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void ConnectivityPlusWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_PLUGIN_CONNECTIVITY_PLUS_WINDOWS_PLUGIN_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/network_manager.h b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/network_manager.h new file mode 100755 index 00000000..19394fec --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/network_manager.h @@ -0,0 +1,50 @@ +#ifndef NETWORK_MANAGER_H +#define NETWORK_MANAGER_H + +// clang-format off +#include +// clang-format on +#include + +#include +#include +#include + +enum class ConnectivityType { None, Ethernet, WiFi, Other, VPN }; + +class NetworkListener; +struct IConnectionPoint; +struct IConnectionPointContainer; +struct INetworkListManager; +struct IUnknown; + +typedef std::function NetworkCallback; + +class NetworkManager { +public: + NetworkManager(); + ~NetworkManager(); + + bool Init(); + void Cleanup(); + + std::set GetConnectivityTypes() const; + + bool StartListen(NetworkCallback pCallback); + void StopListen(); + + bool HasError() const; + int GetError() const; + +private: + std::vector GetConnectedAdapterIds() const; + + DWORD dwCookie = 0; + IUnknown *pUnknown = NULL; + INetworkListManager *pNetworkListManager = NULL; + IConnectionPointContainer *pCPContainer = NULL; + IConnectionPoint *pConnectPoint = NULL; + NetworkListener *pListener = NULL; +}; + +#endif // NETWORK_MANAGER_H diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/network_manager.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/network_manager.cpp new file mode 100755 index 00000000..31822c55 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/network_manager.cpp @@ -0,0 +1,252 @@ +// based on +// https://github.com/PurpleI2P/i2pd/blob/master/Win32/Win32NetState.cpp + +/* + * Copyright (c) 2013-2020, The PurpleI2P Project + * + * This file is part of Purple i2pd project and licensed under BSD3 + * + * See full license text in LICENSE file at top of project tree + */ + +#include "include/connectivity_plus/network_manager.h" + +#include +#include +#include + +#include +#include + +class NetworkListener final : public INetworkEvents { +public: + NetworkListener(NetworkCallback pCb) : pCallback(pCb) {} + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { + AddRef(); + + HRESULT hr = S_OK; + if (IsEqualIID(riid, IID_IUnknown)) { + *ppvObject = (IUnknown *)this; + } else if (IsEqualIID(riid, IID_INetworkEvents)) { + *ppvObject = (INetworkEvents *)this; + } else { + hr = E_NOINTERFACE; + } + return hr; + } + + ULONG STDMETHODCALLTYPE AddRef() { return InterlockedIncrement(&lRef); } + + ULONG STDMETHODCALLTYPE Release() { + LONG lAddend = InterlockedDecrement(&lRef); + if (lRef == 0) { + delete this; + } + return lAddend; + } + + HRESULT STDMETHODCALLTYPE NetworkAdded(GUID networkId) { return S_OK; } + + HRESULT STDMETHODCALLTYPE + NetworkConnectivityChanged(GUID networkId, NLM_CONNECTIVITY newConnectivity) { + Callback(); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE NetworkDeleted(GUID networkId) { return S_OK; } + + HRESULT STDMETHODCALLTYPE + NetworkPropertyChanged(GUID networkId, NLM_NETWORK_PROPERTY_CHANGE flags) { + if (flags & NLM_NETWORK_PROPERTY_CHANGE_CONNECTION) { + Callback(); + } + return S_OK; + } + + void Callback() { + assert(pCallback); + pCallback(); + } + +private: + volatile LONG lRef = 1; + NetworkCallback pCallback = nullptr; +}; + +NetworkManager::NetworkManager() {} + +NetworkManager::~NetworkManager() { + StopListen(); + Cleanup(); +} + +bool NetworkManager::Init() { + CoInitialize(NULL); + + HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, + IID_IUnknown, (void **)&pUnknown); + if (SUCCEEDED(hr)) { + hr = pUnknown->QueryInterface(IID_INetworkListManager, + (void **)&pNetworkListManager); + } + return SUCCEEDED(hr); +} + +void NetworkManager::Cleanup() { + if (pNetworkListManager) { + pNetworkListManager->Release(); + pNetworkListManager = NULL; + } + + if (pUnknown) { + pUnknown->Release(); + pUnknown = NULL; + } + + CoUninitialize(); +} + +std::vector NetworkManager::GetConnectedAdapterIds() const { + std::vector adapterIds; + + IEnumNetworkConnections *connections = NULL; + HRESULT hr = pNetworkListManager->GetNetworkConnections(&connections); + if (hr == S_OK) { + while (true) { + INetworkConnection *connection = NULL; + hr = connections->Next(1, &connection, NULL); + if (hr != S_OK) { + break; + } + + VARIANT_BOOL isConnected = VARIANT_FALSE; + hr = connection->get_IsConnectedToInternet(&isConnected); + if (hr == S_OK && isConnected == VARIANT_TRUE) { + GUID guid; + hr = connection->GetAdapterId(&guid); + if (hr == S_OK) { + adapterIds.push_back(std::move(guid)); + } + } + connection->Release(); + } + connections->Release(); + } + + return adapterIds; +} + +std::set NetworkManager::GetConnectivityTypes() const { + ULONG bufferSize = 15 * 1024; + ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_FRIENDLY_NAME; + std::vector buffer(bufferSize); + PIP_ADAPTER_ADDRESSES addresses = + reinterpret_cast(&buffer.front()); + DWORD rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); + if (rc == ERROR_BUFFER_OVERFLOW) { + buffer.resize(bufferSize); + addresses = reinterpret_cast(&buffer.front()); + rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); + } + + if (rc != NO_ERROR) { + return {ConnectivityType::None}; + } + + std::vector adapterIds = GetConnectedAdapterIds(); + if (adapterIds.empty()) { + return {ConnectivityType::None}; + } + + std::set connectivities; + for (; addresses != NULL; addresses = addresses->Next) { + NET_LUID luid; + rc = ConvertInterfaceIndexToLuid(addresses->IfIndex, &luid); + if (rc != NO_ERROR) { + continue; + } + + GUID guid; + rc = ConvertInterfaceLuidToGuid(&luid, &guid); + if (rc != NO_ERROR) { + continue; + } + + if (std::find(adapterIds.begin(), adapterIds.end(), guid) != + adapterIds.end()) { + // Read more at + // https://learn.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-ip_adapter_addresses_lh + switch (addresses->IfType) { + case IF_TYPE_ETHERNET_CSMACD: + case IF_TYPE_IEEE1394: + connectivities.insert(ConnectivityType::Ethernet); + break; + case IF_TYPE_IEEE80211: + connectivities.insert(ConnectivityType::WiFi); + break; + case IF_TYPE_TUNNEL: + case IF_TYPE_PPP: + connectivities.insert(ConnectivityType::VPN); + break; + default: + connectivities.insert(ConnectivityType::Other); + break; + } + } + } + + if (connectivities.empty()) { + // If no specific connectivity types were found, return a set containing + // only None + return {ConnectivityType::None}; + } + + // Return the set of detected connectivity types + return connectivities; +} + +bool NetworkManager::StartListen(NetworkCallback pCallback) { + if (!pCallback || pListener) { + return false; + } + + HRESULT hr = pNetworkListManager->QueryInterface( + IID_IConnectionPointContainer, (void **)&pCPContainer); + if (SUCCEEDED(hr)) { + hr = pCPContainer->FindConnectionPoint(IID_INetworkEvents, &pConnectPoint); + if (SUCCEEDED(hr)) { + pListener = new NetworkListener(pCallback); + hr = pConnectPoint->Advise((IUnknown *)pListener, &dwCookie); + if (SUCCEEDED(hr)) { + return true; + } + } + } + return false; +} + +void NetworkManager::StopListen() { + if (pConnectPoint) { + pConnectPoint->Unadvise(dwCookie); + pConnectPoint->Release(); + pConnectPoint = NULL; + dwCookie = 0; + } + + if (pCPContainer) { + pCPContainer->Release(); + pCPContainer = NULL; + } + + if (pListener) { + pListener->Release(); + pListener = NULL; + } +} + +bool NetworkManager::HasError() const { return GetLastError() != 0; } + +int NetworkManager::GetError() const { return GetLastError(); } diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus deleted file mode 120000 index 3eb57813..00000000 --- a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/ \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/CHANGELOG.md b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/CHANGELOG.md new file mode 100755 index 00000000..8e7f877d --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/CHANGELOG.md @@ -0,0 +1,471 @@ +## 11.3.0 + + - **FEAT**(device_info_plus): Add User Device Name in Android (PR [#3437](https://github.com/fluttercommunity/plus_plugins/issues/3437)) ([#3456](https://github.com/fluttercommunity/plus_plugins/issues/3456)). ([8c38a31d](https://github.com/fluttercommunity/plus_plugins/commit/8c38a31d7c1073d7011ec3e3193f6b99b3851ef1)) + +## 11.2.2 + + - **FIX**(device_info_plus): Replace throwing exception with returning default values on Windows ([#3445](https://github.com/fluttercommunity/plus_plugins/issues/3445)). ([084730f8](https://github.com/fluttercommunity/plus_plugins/commit/084730f82436b474b31b16f6dc2d7b90585e899f)) + - **DOCS**(device_info_plus): Update the documentation URL for property descriptions. ([#3441](https://github.com/fluttercommunity/plus_plugins/issues/3441)). ([743bec62](https://github.com/fluttercommunity/plus_plugins/commit/743bec626c909fdc8ba6d087006568cca60563d8)) + +## 11.2.1 + + - **FIX**(device_info_plus): Resolve compilation issues with SPM enabled ([#3405](https://github.com/fluttercommunity/plus_plugins/issues/3405)). ([3f098c30](https://github.com/fluttercommunity/plus_plugins/commit/3f098c30320e1595c06b093e8eb9827a44435c5d)) + - **FIX**(device_info_plus): device memory null error on Safari and Firefox ([#3401](https://github.com/fluttercommunity/plus_plugins/issues/3401)). ([2b7cb088](https://github.com/fluttercommunity/plus_plugins/commit/2b7cb0888cd725dc69e409590861fe8118058c4d)) + - **FIX**(device_info_plus): add @Suppress(deprecate) to Build.SERIAL ([#3402](https://github.com/fluttercommunity/plus_plugins/issues/3402)). ([8e70d3f3](https://github.com/fluttercommunity/plus_plugins/commit/8e70d3f33d5f1c005dbb1aef733a8a8578989bac)) + +## 11.2.0 + + - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) + - **FIX**(device_info_plus): fix the error in the e2e test. ([#3382](https://github.com/fluttercommunity/plus_plugins/issues/3382)). ([3d06bf0e](https://github.com/fluttercommunity/plus_plugins/commit/3d06bf0ed8f1029df1230e4be6e75537abfcb19f)) + - **FIX**(device_info_plus): Set correct Flutter and Dart versions requirements ([#3362](https://github.com/fluttercommunity/plus_plugins/issues/3362)). ([77861523](https://github.com/fluttercommunity/plus_plugins/commit/778615231c376c829d6241e7988f15a77bcaeb55)) + - **FEAT**(device_info_plus): Return model name for iOS and MacOS devices ([#3358](https://github.com/fluttercommunity/plus_plugins/issues/3358)). ([63ca4cd8](https://github.com/fluttercommunity/plus_plugins/commit/63ca4cd8127e010650468a79532dd3a6047d2b31)) + - **FEAT**(device_info_plus): Add the isiOSAppOnMac property for the iOS platform. ([#3383](https://github.com/fluttercommunity/plus_plugins/issues/3383)). ([e9077845](https://github.com/fluttercommunity/plus_plugins/commit/e9077845342023d325280985234b6a09d245ac02)) + +## 11.1.1 + + - **FIX**(device_info_plus): Update privacy manifest paths ([#3347](https://github.com/fluttercommunity/plus_plugins/issues/3347)). ([46df2302](https://github.com/fluttercommunity/plus_plugins/commit/46df23023a5ba6c98edd31d5fd06bec5df40bd3b)) + +## 11.1.0 + + - **FIX**(device_info_plus): Ignore `MissingPermission` lint error on Android ([#3317](https://github.com/fluttercommunity/plus_plugins/issues/3317)). ([6469523f](https://github.com/fluttercommunity/plus_plugins/commit/6469523fb14f32f7aa23892183693a8f502992d3)) + - **FEAT**(device_info_plus): Add Swift Package Manager support ([#3167](https://github.com/fluttercommunity/plus_plugins/issues/3167)). ([6a347cb1](https://github.com/fluttercommunity/plus_plugins/commit/6a347cb106182d68329cd32827938e26bc7e7b00)) + +## 11.0.0 + +> Note: This release has breaking changes. + + - **FIX**(all): Clean up macOS Privacy Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) + - **FIX**(all): Add macOS Privacy Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) + - **FIX**(device_info_plus): Fix type cast of digitalProductId on windows ([#3188](https://github.com/fluttercommunity/plus_plugins/issues/3188)). ([91f48a6b](https://github.com/fluttercommunity/plus_plugins/commit/91f48a6bc7d11c4238c9539ca06e6fa768995580)) + - **BREAKING** **FIX**(device_info_plus): fixed webasm compliance ([#3254](https://github.com/fluttercommunity/plus_plugins/issues/3254)). ([e35e2123](https://github.com/fluttercommunity/plus_plugins/commit/e35e2123451fc103bbb6f6d94f71ebced2ae8af5)) + +## 10.1.2 + + - **DOCS**(device_info_plus): Update plugin requirements in README ([#3162](https://github.com/fluttercommunity/plus_plugins/issues/3162)). ([6cfa950f](https://github.com/fluttercommunity/plus_plugins/commit/6cfa950f66fec649093b6c44755dc06a3a23319e)) + +## 10.1.1 + + - **CHORE**(device_info_plus): Use `>=0.5.0 < 2.0.0` version range for package:web. + - **FIX**(device_info_plus): fix integration_test iOS ([#2958](https://github.com/fluttercommunity/plus_plugins/issues/2958)). ([93ab854e](https://github.com/fluttercommunity/plus_plugins/commit/93ab854ee76a3de48387b6c54ddaeccb01cf49a9)) + - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) + - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) + +## 10.1.0 + + - **REFACTOR**(device_info_plus): Migrate Android example to use the new plugins declaration ([#2769](https://github.com/fluttercommunity/plus_plugins/issues/2769)). ([6103b155](https://github.com/fluttercommunity/plus_plugins/commit/6103b1559d6f9383bd66460bf7717afeeeb51d86)) + - **FIX**(device_info_plus): WASM-compatible conditional imports ([#2826](https://github.com/fluttercommunity/plus_plugins/issues/2826)). ([11200cf4](https://github.com/fluttercommunity/plus_plugins/commit/11200cf4eb38bfa6bc83e955a3ceff7b8fc72493)) + - **FEAT**(device_info_plus): Add isLowRamDevice property to AndroidDeviceInfo ([#2765](https://github.com/fluttercommunity/plus_plugins/issues/2765)). ([1376b035](https://github.com/fluttercommunity/plus_plugins/commit/1376b0359fd39172cfb54595178313c73f5d1942)) + - **DOCS**(device_info_plus): Add iOS name property entitlements info ([#2756](https://github.com/fluttercommunity/plus_plugins/issues/2756)). ([d21f285a](https://github.com/fluttercommunity/plus_plugins/commit/d21f285a1d26e7a512c4a9aea579de9680a6ca48)) + +## 10.0.1 + +> Note: This release has breaking changes. + +In this release plugin migrated to package:web, meaning that it now supports WASM! + +Plugin now requires the following: +- Flutter >=3.19.0 +- Dart >=3.3.0 +- compileSDK 34 for Android part +- Java 17 for Android part +- Gradle 8.4 for Android part +- + - **BREAKING** **REFACTOR**(device_info_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2589](https://github.com/fluttercommunity/plus_plugins/issues/2589)). ([1c586abf](https://github.com/fluttercommunity/plus_plugins/commit/1c586abf7ee351927242a70cb88e2e36140cec9e)) + - **BREAKING** **FIX**(device_info_plus): Remove Display Metrics from Android Device Info ([#2731](https://github.com/fluttercommunity/plus_plugins/issues/2731)). ([c5af3322](https://github.com/fluttercommunity/plus_plugins/commit/c5af332207e44902ac92765da72d2acb213fae91)) + - **BREAKING** **FEAT**(device_info_plus): migrate to package:web ([#2624](https://github.com/fluttercommunity/plus_plugins/issues/2624)). ([154e76ca](https://github.com/fluttercommunity/plus_plugins/commit/154e76ca2f9e8c1ccdaa6e2076426002c9d372a3)) + - **BREAKING** **BUILD**(device_info_plus): Target Java 17 on Android ([#2725](https://github.com/fluttercommunity/plus_plugins/issues/2725)). ([aa826dea](https://github.com/fluttercommunity/plus_plugins/commit/aa826deac5ef8136ce922f5823be2e7f90f828e9)) + - **BREAKING** **BUILD**(device_info_plus): Update to target and compile SDK 34 ([#2704](https://github.com/fluttercommunity/plus_plugins/pull/2704)). ([a3cd72f](https://github.com/fluttercommunity/plus_plugins/commit/a3cd72f86ba47f43c507f8b83f89aac7519404de)) + - **FIX**(device_info_plus): remove unnecessary print ([#2607](https://github.com/fluttercommunity/plus_plugins/issues/2607)). ([5d515816](https://github.com/fluttercommunity/plus_plugins/commit/5d5158169f75c50f15588c10e07af2e25f950c23)) + - **FIX**(device_info_plus): return type of isPhysicalDevice as boolean for ios ([#2508](https://github.com/fluttercommunity/plus_plugins/issues/2508)). ([e3a983bb](https://github.com/fluttercommunity/plus_plugins/commit/e3a983bbf0b0bb70c7c50835ddb7f3c4a46b7122)) + - **FIX**(device_info_plus): Add iOS Privacy Info ([#2582](https://github.com/fluttercommunity/plus_plugins/issues/2582)). ([34fe31eb](https://github.com/fluttercommunity/plus_plugins/commit/34fe31eb29e21fa9ea336e61d8df6858eb441a00)) + - **FEAT**(device_info_plus): Update min iOS target to 12 ([#2658](https://github.com/fluttercommunity/plus_plugins/issues/2658)). ([a3436100](https://github.com/fluttercommunity/plus_plugins/commit/a3436100fabd04a4d4db7ac09128b5b5962579d3)) + - **FEAT**(device_info_plus): LinuxDeviceInfo toString method ([#2652](https://github.com/fluttercommunity/plus_plugins/issues/2652)). ([f2fbcdb8](https://github.com/fluttercommunity/plus_plugins/commit/f2fbcdb813b62dcb76c18b00e51383e6643a93ed)) + +## 10.0.0 + +> Note: This release was retracted due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). + +## 9.1.2 + + - **FIX**(device_info_plus): fix crash on non-standard Digital Product IDs ([#2537](https://github.com/fluttercommunity/plus_plugins/issues/2537)). ([7b318b5c](https://github.com/fluttercommunity/plus_plugins/commit/7b318b5cd8496cf7d31c62314eb9bae17f9ef8d6)) + +## 9.1.1 + + - **FIX**(device_info_plus): Fix deprecation warning on MacOS ([#2377](https://github.com/fluttercommunity/plus_plugins/issues/2377)). ([56a6d0ff](https://github.com/fluttercommunity/plus_plugins/commit/56a6d0ff3752570de89f00876eb7181d662a0465)) + +## 9.1.0 + +> Info: This release is a replacement for release 10.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. + + - **FIX**(device_info_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2256](https://github.com/fluttercommunity/plus_plugins/issues/2256)). ([313ec2c3](https://github.com/fluttercommunity/plus_plugins/commit/313ec2c328f34b278f197ee1f2d896f8820ac789)) + - **FIX**(device_info_plus): Revert bump compileSDK to 34 ([#2230](https://github.com/fluttercommunity/plus_plugins/issues/2230)). ([2ba5b054](https://github.com/fluttercommunity/plus_plugins/commit/2ba5b054948f48a9aae72c8a63b39f6536ab678d)) + - **FIX**(device_info_plus): Update exports to avoid web compatibility issues ([#2028](https://github.com/fluttercommunity/plus_plugins/issues/2028)). ([6c216053](https://github.com/fluttercommunity/plus_plugins/commit/6c2160537dc51493adc5bf22cd480a52582845b0)) + - **FIX**(device_info_plus): Regenerate iOS and MacOS example apps ([#1868](https://github.com/fluttercommunity/plus_plugins/issues/1868)). ([6e1111ac](https://github.com/fluttercommunity/plus_plugins/commit/6e1111acff40fef6f77fe2561810d679bafe938c)) + - **FEAT**(device_info_plus): Remove deprecated VALID_ARCHS iOS property ([#2022](https://github.com/fluttercommunity/plus_plugins/issues/2022)). ([13053295](https://github.com/fluttercommunity/plus_plugins/commit/13053295137201b34a6bf52e494ccf77e0321b18)) + - **DOCS**(device_info_plus): Add note about arch returned value on MacOS ([#2220](https://github.com/fluttercommunity/plus_plugins/issues/2220)). ([80409e2a](https://github.com/fluttercommunity/plus_plugins/commit/80409e2ab13a6379b9101034ad453517151a719a)) + - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) + +## 9.0.3 + + - **FIX**(device_info_plus): Regenerate iOS and MacOS example apps ([#1868](https://github.com/fluttercommunity/plus_plugins/issues/1868)). ([6e1111ac](https://github.com/fluttercommunity/plus_plugins/commit/6e1111acff40fef6f77fe2561810d679bafe938c)) + - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) + +## 9.0.2 + + - **DOCS**(device_info_plus): Add links to Android and iOS docs to every field ([#1857](https://github.com/fluttercommunity/plus_plugins/issues/1857)). ([89eb5217](https://github.com/fluttercommunity/plus_plugins/commit/89eb52177c90d5453ba512e73472536fc8a03c9a)) + +## 9.0.1 + + - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) + - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) + - **CHORE**(device_info_plus): Win32 dependency upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) + +## 9.0.0 + +> Note: This release has breaking changes. + + - **CHORE**(device_info_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 + - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. + - **BREAKING** **CHORE**(device_info_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1781). + - **REFACTOR**(device_info_plus): Refactor Windows implementation (#1772). + - **REFACTOR**(device_info_plus): Remove redundant checks for PRODUCT strings with sdk (#1745). + - **REFACTOR**(device_info_plus): Declare proper nullability for iOS properties (#1728). + +## 8.2.2 + + - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). + +## 8.2.1 + + - **FIX**(device_info_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1702). + +## 8.2.0 + + - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). + - **FEAT**(device_info_plus): add major, minor and patch versions to macos (#1649). + +## 8.1.0 + + - **FEAT**: Add serialNumber property to AndroidDeviceInfo (#1349). + - **DOCS**: Updates for READMEs and website pages (#1389). + - **DOCS**: Explain how to get serial number on Android (#1390). + - **DOCS**: Add info about iOS 16 changes to device name (#1356). + +## 8.0.0 + +> Note: This release has breaking changes. + + - **DOCS**: Document toMap deprecation (#1292). + - **BREAKING** **FEAT**: refactor of device_info_plus platform implementation (#1293). + +## 7.0.1 + + - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). + +## 7.0.0 + +> Note: This release has breaking changes. + + - **REFACTOR**: Migrate Android part to Kotlin, update Android dependencies (#1245). + - **FIX**: add `@Deprecated` annotation to `toMap` method (#1142). + - **DOCS**: Add info about Android properties availability, update API docs links (#1243). + - **BREAKING** **REFACTOR**: two-package federated architecture (#1228). + +## 6.0.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FEAT**: Add support of Android display metrics (#829). + +## 5.0.5 + + - Update a dependency to the latest release. + +## 5.0.4 + + - **FIX**: fixed wrong dependency version #1175. + +## 5.0.3 + + - **FIX**: fix version dependency. + +## 5.0.2 + + - **CHORE**: Version tagging using melos. + +## 5.0.1 + +- Fixing federated plugin architecture versions. + +## 5.0.0 + +- Re-introduce: Added more information to `WindowsDeviceInfo`. +- device_info_plus_platform_interface to 4.0.0 + +## 4.1.3 + +- Detects iOS simulator device id instead of simulator's underlying architecture. + +## 4.1.2 + +- Redo changes in 4.1.0 +- device_info_plus_platform_interface to 3.0.0 + +## 4.1.1 + +- Revert changes in 4.1.0 + +## 4.1.0 + +- Remove `androidId` (that already got removed from the method channel in 4.0.0, thus always returned null) +- There is a **new, separate [pub.dev package](https://pub.dev/packages/android_id) for getting the correct `androidId`** + +## 4.0.3 + +- Reverted changes in 4.0.2 + +## 4.0.2 + +- Added more information to `WindowsDeviceInfo`. + +## 4.0.1 + +- Update dependencies + +## 4.0.0 + +- **Breaking change** Remove `AndroidId` getter to avoid Google Play policies violations +- Update flutter_lints to 2.0.1 +- Remove explicit `test` dependency to use `flutter_test` from Flutter SDK + +## 3.2.4 + +- Update the description of getAndroidId method + +## 3.2.3 + +- Fix crash on macOS running on Apple M1 + +## 3.2.2 + +- Fix embedding issue in example +- Update Android dependencies in example + +## 3.2.1 + +- iOS: fix `identifierForVendor` (can be `null` in rare circumstances) +- Use automatic plugin registration on Linux and Windows +- Fix warnings when building for macOS + +## 3.2.0 + +- add `deviceInfo` + +## 3.1.1 + +- add toMap to WebBrowserInfo + +## 3.1.0 + +- add System GUID to MacOS + +## 3.0.1 + +- Upgrade Android compile SDK version +- Several code improvements + +## 3.0.0 + +- Remove deprecated method `registerWith` (of Android v1 embedding) + +## 2.2.0 + +- migrate integration_test to flutter sdk + +## 2.1.0 + +- add toMap to models + +## 2.0.1 + +- Android: migrate to mavenCentral + +## 2.0.0 + +- WebBrowserInfo properties are now nullable + +## 1.0.1 + +- Improve documentation + +## 1.0.0 + +- Migrated to null safety +- Update dependencies. + +## 0.7.2 + +- Update dependencies. + +## 0.7.1 + +- Fix macOS support. + +## 0.7.0 + +- Add macOS support via `device_info_plus_macos`. + +## 0.6.0 + +- Rename method channel to avoid conflicts. + +## 0.5.0 + +- Transfer to plus-plugins monorepo + +## 0.4.2+8 + +- Transfer package to Flutter Community under new name `device_info_plus`. + +## 0.4.2+7 + +- Port device_info plugin to use platform interface. + +## 0.4.2+6 + +- Moved everything from device_info to device_info/device_info + +## 0.4.2+5 + +- Update package:e2e reference to use the local version in the flutter/plugins + repository. + +## 0.4.2+4 + +Update lower bound of dart dependency to 2.1.0. + +## 0.4.2+3 + +- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). + +## 0.4.2+2 + +- Fix CocoaPods podspec lint warnings. + +## 0.4.2+1 + +- Bump the minimum Flutter version to 1.12.13+hotfix.5. +- Remove deprecated API usage warning in AndroidIntentPlugin.java. +- Migrates the Android example to V2 embedding. +- Bumps AGP to 3.6.1. + +## 0.4.2 + +- Add systemFeatures to AndroidDeviceInfo. + +## 0.4.1+5 + +- Make the pedantic dev_dependency explicit. + +## 0.4.1+4 + +- Remove the deprecated `author:` field from pubspec.yaml +- Migrate the plugin to the pubspec platforms manifest. +- Require Flutter SDK 1.10.0 or greater. + +## 0.4.1+3 + +- Fix pedantic errors. Adds some missing documentation and fixes unawaited + futures in the tests. + +## 0.4.1+2 + +- Remove AndroidX warning. + +## 0.4.1+1 + +- Include lifecycle dependency as a compileOnly one on Android to resolve + potential version conflicts with other transitive libraries. + +## 0.4.1 + +- Support the v2 Android embedding. +- Update to AndroidX. +- Migrate to using the new e2e test binding. +- Add a e2e test. + +## 0.4.0+4 + +- Define clang module for iOS. + +## 0.4.0+3 + +- Update and migrate iOS example project. + +## 0.4.0+2 + +- Bump minimum Flutter version to 1.5.0. +- Add missing template type parameter to `invokeMethod` calls. +- Replace invokeMethod with invokeMapMethod wherever necessary. + +## 0.4.0+1 + +- Log a more detailed warning at build time about the previous AndroidX + migration. + +## 0.4.0 + +- **Breaking change**. Migrate from the deprecated original Android Support + Library to AndroidX. This shouldn't result in any functional changes, but it + requires any Android apps using this plugin to [also + migrate](https://developer.android.com/jetpack/androidx/migrate) if they're + using the original support library. + +## 0.3.0 + +- Added ability to get Android ID for Android devices + +## 0.2.1 + +- Updated Gradle tooling to match Android Studio 3.1.2. + +## 0.2.0 + +- **Breaking change**. Set SDK constraints to match the Flutter beta release. + +## 0.1.2 + +- Fixed Dart 2 type errors. + +## 0.1.1 + +- Simplified and upgraded Android project template to Android SDK 27. +- Updated package description. + +## 0.1.0 + +- **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin + 3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in + order to use this version of the plugin. Instructions can be found + [here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1). + +## 0.0.5 + +- Added FLT prefix to iOS types + +## 0.0.4 + +- Fixed Java/Dart communication error with empty lists + +## 0.0.3 + +- Added support for utsname + +## 0.0.2 + +- Fixed broken type comparison +- Added "isPhysicalDevice" field, detecting emulators/simulators + +## 0.0.1 + +- Implements platform-specific device/OS properties diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/LICENSE b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/LICENSE new file mode 100755 index 00000000..7b995420 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/LICENSE @@ -0,0 +1,27 @@ +Copyright 2017 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/README.md new file mode 100755 index 00000000..fdfd7da5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/README.md @@ -0,0 +1,76 @@ +# device_info_plus + +[![pub package](https://img.shields.io/pub/v/device_info_plus.svg)](https://pub.dev/packages/device_info_plus) +[![pub points](https://img.shields.io/pub/points/device_info_plus?color=2E8B57&label=pub%20points)](https://pub.dev/packages/device_info_plus/score) +[![device_info_plus](https://github.com/fluttercommunity/plus_plugins/actions/workflows/device_info_plus.yaml/badge.svg)](https://github.com/fluttercommunity/plus_plugins/actions/workflows/device_info_plus.yaml) + +[](https://flutter.dev/docs/development/packages-and-plugins/favorites) + +Get current device information from within the Flutter application. + +## Platform Support + +| Android | iOS | MacOS | Web | Linux | Windows | +| :-----: | :-: | :---: | :-: | :---: | :-----: | +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | + +## Requirements + +- Flutter >=3.22.0 +- Dart >=3.4.0 <4.0.0 +- iOS >=12.0 +- MacOS >=10.14 +- Android `compileSDK` 34 +- Java 17 +- Android Gradle Plugin >=8.3.0 +- Gradle wrapper >=8.4 + +# Usage + +Import `package:device_info_plus/device_info_plus.dart`, instantiate `DeviceInfoPlugin` +and use the Android and iOS, Web getters to get platform-specific device +information. + +Example: + +```dart +import 'package:device_info_plus/device_info_plus.dart'; + +DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); +AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; +print('Running on ${androidInfo.model}'); // e.g. "Moto G (4)" + +IosDeviceInfo iosInfo = await deviceInfo.iosInfo; +print('Running on ${iosInfo.utsname.machine}'); // e.g. "iPod7,1" + +WebBrowserInfo webBrowserInfo = await deviceInfo.webBrowserInfo; +print('Running on ${webBrowserInfo.userAgent}'); // e.g. "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0" +``` + +The plugin provides a `data` method that returns platform-specific device +information in a generic way, which can be used for crash-reporting purposes. + +However, the data provided by this `data` method is currently not serializable +(i.e. it is not 100% JSON compatible) and shouldn't be treated as such. + +```dart +import 'package:device_info_plus/device_info_plus.dart'; + +final deviceInfoPlugin = DeviceInfoPlugin(); +final deviceInfo = await deviceInfoPlugin.deviceInfo; +final allInfo = deviceInfo.data; +``` + +### Android + +To get serial number on Android your app needs to meet one of official [requirements](https://developer.android.com/reference/android/os/Build#getSerial()). +In case the app doesn't meet any of requirements plugin will return `unknown`. + +### iOS + +The `name` property exposes the assigned device name by the owner. This value is obtained from the property `UIDevice.current.name`. +This property requires special entitlement [com.apple.developer.device-information.user-assigned-device-name](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_device-information_user-assigned-device-name) in iOS 16 and later, otherwise, the property `name` will always be `iPad` or `iPhone`. + +## Learn more + +- [API Documentation](https://pub.dev/documentation/device_info_plus/latest/device_info_plus/device_info_plus-library.html) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/build.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/build.gradle new file mode 100755 index 00000000..5213cd0a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/build.gradle @@ -0,0 +1,53 @@ +group 'dev.fluttercommunity.plus.device_info' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.7.22' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.3.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdk 34 + + namespace 'dev.fluttercommunity.plus.device_info' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = 17 + } + + defaultConfig { + minSdk 19 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + lintOptions { + disable 'InvalidPackage', 'MissingPermission' + } + + dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle.properties new file mode 100755 index 00000000..8bd86f68 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..e411586a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/settings.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/settings.gradle new file mode 100755 index 00000000..0e75718c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'device_info' diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/AndroidManifest.xml new file mode 100755 index 00000000..412ea27f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/DeviceInfoPlusPlugin.kt b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/DeviceInfoPlusPlugin.kt new file mode 100755 index 00000000..3ba8c921 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/DeviceInfoPlusPlugin.kt @@ -0,0 +1,32 @@ +package dev.fluttercommunity.plus.device_info + +import android.app.ActivityManager +import android.content.Context +import android.content.pm.PackageManager +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MethodChannel + +/** DeviceInfoPlusPlugin */ +class DeviceInfoPlusPlugin : FlutterPlugin { + + private lateinit var methodChannel: MethodChannel + + override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { + setupMethodChannel(binding.binaryMessenger, binding.applicationContext) + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + methodChannel.setMethodCallHandler(null) + } + + private fun setupMethodChannel(messenger: BinaryMessenger, context: Context) { + methodChannel = MethodChannel(messenger, "dev.fluttercommunity.plus/device_info") + val packageManager: PackageManager = context.packageManager + val activityManager: ActivityManager = + context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + val contentResolver = context.contentResolver + val handler = MethodCallHandlerImpl(packageManager, activityManager, contentResolver) + methodChannel.setMethodCallHandler(handler) + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt new file mode 100755 index 00000000..4cfdf4f9 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt @@ -0,0 +1,114 @@ +package dev.fluttercommunity.plus.device_info + +import android.app.ActivityManager +import android.content.ContentResolver +import android.content.pm.FeatureInfo +import android.content.pm.PackageManager +import android.os.Build +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import kotlin.collections.HashMap +import android.provider.Settings + +/** + * The implementation of [MethodChannel.MethodCallHandler] for the plugin. Responsible for + * receiving method calls from method channel. + */ +internal class MethodCallHandlerImpl( + private val packageManager: PackageManager, + private val activityManager: ActivityManager, + private val contentResolver: ContentResolver, +) : MethodCallHandler { + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + if (call.method.equals("getDeviceInfo")) { + val build: MutableMap = HashMap() + + build["board"] = Build.BOARD + build["bootloader"] = Build.BOOTLOADER + build["brand"] = Build.BRAND + build["device"] = Build.DEVICE + build["display"] = Build.DISPLAY + build["fingerprint"] = Build.FINGERPRINT + build["hardware"] = Build.HARDWARE + build["host"] = Build.HOST + build["id"] = Build.ID + build["manufacturer"] = Build.MANUFACTURER + build["model"] = Build.MODEL + build["product"] = Build.PRODUCT + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { + build["name"] = Settings.Global.getString(contentResolver, Settings.Global.DEVICE_NAME) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + build["supported32BitAbis"] = listOf(*Build.SUPPORTED_32_BIT_ABIS) + build["supported64BitAbis"] = listOf(*Build.SUPPORTED_64_BIT_ABIS) + build["supportedAbis"] = listOf(*Build.SUPPORTED_ABIS) + } else { + build["supported32BitAbis"] = emptyList() + build["supported64BitAbis"] = emptyList() + build["supportedAbis"] = emptyList() + } + + build["tags"] = Build.TAGS + build["type"] = Build.TYPE + build["isPhysicalDevice"] = !isEmulator + build["systemFeatures"] = getSystemFeatures() + + val version: MutableMap = HashMap() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + version["baseOS"] = Build.VERSION.BASE_OS + version["previewSdkInt"] = Build.VERSION.PREVIEW_SDK_INT + version["securityPatch"] = Build.VERSION.SECURITY_PATCH + } + version["codename"] = Build.VERSION.CODENAME + version["incremental"] = Build.VERSION.INCREMENTAL + version["release"] = Build.VERSION.RELEASE + version["sdkInt"] = Build.VERSION.SDK_INT + build["version"] = version + build["isLowRamDevice"] = activityManager.isLowRamDevice + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + build["serialNumber"] = try { + Build.getSerial() + } catch (ex: SecurityException) { + Build.UNKNOWN + } + } else { + @Suppress("DEPRECATION") + build["serialNumber"] = Build.SERIAL + } + + result.success(build) + } else { + result.notImplemented() + } + } + + private fun getSystemFeatures(): List { + val featureInfos: Array = packageManager.systemAvailableFeatures + return featureInfos + .filterNot { featureInfo -> featureInfo.name == null } + .map { featureInfo -> featureInfo.name } + } + + /** + * A simple emulator-detection based on the flutter tools detection logic and a couple of legacy + * detection systems + */ + private val isEmulator: Boolean + get() = ((Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) + || Build.FINGERPRINT.startsWith("generic") + || Build.FINGERPRINT.startsWith("unknown") + || Build.HARDWARE.contains("goldfish") + || Build.HARDWARE.contains("ranchu") + || Build.MODEL.contains("google_sdk") + || Build.MODEL.contains("Emulator") + || Build.MODEL.contains("Android SDK built for x86") + || Build.MANUFACTURER.contains("Genymotion") + || Build.PRODUCT.contains("sdk") + || Build.PRODUCT.contains("vbox86p") + || Build.PRODUCT.contains("emulator") + || Build.PRODUCT.contains("simulator")) +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/README.md new file mode 100755 index 00000000..53c05c2c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/README.md @@ -0,0 +1,5 @@ +# device_info_example + +Demonstrates how to use the `device_info_plus` plugin[1]. + +[1]: ../ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/build.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/build.gradle new file mode 100755 index 00000000..1e70360c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/build.gradle @@ -0,0 +1,66 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + compileSdk 34 + + namespace 'io.flutter.plugins.deviceinfoexample.example' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = 17 + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + applicationId "io.flutter.plugins.deviceinfoexample.example" + minSdk 21 + targetSdk 34 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + 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.debug + } + } +} + +flutter { + source '../..' +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/debug/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/debug/AndroidManifest.xml new file mode 100755 index 00000000..175e81dc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/AndroidManifest.xml new file mode 100755 index 00000000..d75557c5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/kotlin/io/flutter/plugins/deviceinfoexample/example/MainActivity.kt b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/kotlin/io/flutter/plugins/deviceinfoexample/example/MainActivity.kt new file mode 100755 index 00000000..e2bd9925 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/kotlin/io/flutter/plugins/deviceinfoexample/example/MainActivity.kt @@ -0,0 +1,21 @@ +package io.flutter.plugins.deviceinfoexample.example + +import android.os.Build +import android.os.Bundle +import android.os.StrictMode +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + // Ensures correct use of Activity Context to obtain the WindowManager + StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder() + .detectIncorrectContextUse() + .penaltyLog() + .penaltyDeath() + .build()) + } + super.onCreate(savedInstanceState) + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/drawable/launch_background.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100755 index 00000000..304732f8 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100755 index 00000000..db77bb4b Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100755 index 00000000..17987b79 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100755 index 00000000..09d43914 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100755 index 00000000..d5f1c8d3 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100755 index 00000000..4d6372ee Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/values/styles.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/values/styles.xml new file mode 100755 index 00000000..1f83a33f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/profile/AndroidManifest.xml b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/profile/AndroidManifest.xml new file mode 100755 index 00000000..175e81dc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/build.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/build.gradle new file mode 100755 index 00000000..bc157bd1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle.properties new file mode 100755 index 00000000..d9cf55df --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..448814c7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Oct 05 15:15:38 CEST 2021 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/settings.gradle b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/settings.gradle new file mode 100755 index 00000000..fa3b4d08 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/settings.gradle @@ -0,0 +1,25 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.3.1" apply false + id "org.jetbrains.kotlin.android" version "1.9.23" apply false +} + +include ":app" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/integration_test/device_info_plus_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/integration_test/device_info_plus_test.dart new file mode 100755 index 00000000..2cb0a980 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/integration_test/device_info_plus_test.dart @@ -0,0 +1,236 @@ +// Copyright 2019, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late IosDeviceInfo iosInfo; + late AndroidDeviceInfo androidInfo; + late WebBrowserInfo webBrowserInfo; + late WindowsDeviceInfo windowsInfo; + late LinuxDeviceInfo linuxInfo; + late MacOsDeviceInfo macosInfo; + late BaseDeviceInfo deviceInfo; + + setUpAll(() async { + final deviceInfoPlugin = DeviceInfoPlugin(); + if (kIsWeb) { + webBrowserInfo = await deviceInfoPlugin.webBrowserInfo; + } else { + if (Platform.isIOS) { + iosInfo = await deviceInfoPlugin.iosInfo; + } else if (Platform.isAndroid) { + androidInfo = await deviceInfoPlugin.androidInfo; + } else if (Platform.isWindows) { + windowsInfo = await deviceInfoPlugin.windowsInfo; + } else if (Platform.isLinux) { + linuxInfo = await deviceInfoPlugin.linuxInfo; + } else if (Platform.isMacOS) { + macosInfo = await deviceInfoPlugin.macOsInfo; + } + } + + deviceInfo = await deviceInfoPlugin.deviceInfo; + }); + + testWidgets('Can get non-null device model', (WidgetTester tester) async { + if (kIsWeb) { + expect(webBrowserInfo.userAgent, isNotNull); + expect(deviceInfo, same(webBrowserInfo)); + } else { + if (Platform.isIOS) { + expect(iosInfo.model, isNotNull); + expect(deviceInfo, same(iosInfo)); + } else if (Platform.isAndroid) { + expect(androidInfo.model, isNotNull); + expect(deviceInfo, same(androidInfo)); + } else if (Platform.isWindows) { + expect(windowsInfo.computerName, isNotNull); + expect(deviceInfo, same(windowsInfo)); + } else if (Platform.isLinux) { + expect(linuxInfo.name, isNotNull); + expect(deviceInfo, same(linuxInfo)); + } else if (Platform.isMacOS) { + expect(macosInfo.computerName, isNotNull); + expect(deviceInfo, same(macosInfo)); + } + } + }); + + testWidgets('Can get non-null iOS utsname fields', + (WidgetTester tester) async { + expect(iosInfo.utsname.machine, isNotNull); + expect(iosInfo.utsname.nodename, isNotNull); + expect(iosInfo.utsname.release, isNotNull); + expect(iosInfo.utsname.sysname, isNotNull); + expect(iosInfo.utsname.version, isNotNull); + }, skip: !Platform.isIOS); + + testWidgets('Check all android info values are available', + (WidgetTester tester) async { + if (androidInfo.version.sdkInt >= 23) { + expect(androidInfo.version.baseOS, isNotNull); + expect(androidInfo.version.previewSdkInt, isNotNull); + expect(androidInfo.version.securityPatch, isNotNull); + } + + expect(androidInfo.version.codename, isNotNull); + expect(androidInfo.version.incremental, isNotNull); + expect(androidInfo.version.release, isNotNull); + expect(androidInfo.version.sdkInt, isNotNull); + expect(androidInfo.board, isNotNull); + expect(androidInfo.bootloader, isNotNull); + expect(androidInfo.brand, isNotNull); + expect(androidInfo.device, isNotNull); + expect(androidInfo.display, isNotNull); + expect(androidInfo.fingerprint, isNotNull); + expect(androidInfo.hardware, isNotNull); + + expect(androidInfo.host, isNotNull); + expect(androidInfo.id, isNotNull); + expect(androidInfo.manufacturer, isNotNull); + expect(androidInfo.model, isNotNull); + expect(androidInfo.product, isNotNull); + expect(androidInfo.name, isNotNull); + + expect(androidInfo.supported32BitAbis, isNotNull); + expect(androidInfo.supported64BitAbis, isNotNull); + expect(androidInfo.supportedAbis, isNotNull); + + expect(androidInfo.tags, isNotNull); + expect(androidInfo.type, isNotNull); + expect(androidInfo.isPhysicalDevice, isNotNull); + expect(androidInfo.systemFeatures, isNotNull); + expect(androidInfo.serialNumber, isNotNull); + }, skip: !Platform.isAndroid); + + testWidgets('Check all macos info values are available', + ((WidgetTester tester) async { + expect(macosInfo.computerName, isNotNull); + expect(macosInfo.hostName, isNotNull); + expect(macosInfo.arch, isNotNull); + expect(macosInfo.model, isNotNull); + expect(macosInfo.modelName, isNotNull); + expect(macosInfo.kernelVersion, isNotNull); + expect(macosInfo.osRelease, isNotNull); + expect(macosInfo.activeCPUs, isNotNull); + expect(macosInfo.memorySize, isNotNull); + expect(macosInfo.cpuFrequency, isNotNull); + expect(macosInfo.systemGUID, isNotNull); + }), skip: !Platform.isMacOS); + + testWidgets('Check all Linux info values are available', + ((WidgetTester tester) async { + expect(linuxInfo.name, isNotNull); + expect(linuxInfo.version, isNotNull); + expect(linuxInfo.id, isNotNull); + expect(linuxInfo.idLike, isNotNull); + expect(linuxInfo.versionCodename, isNotNull); + expect(linuxInfo.versionId, isNotNull); + expect(linuxInfo.prettyName, isNotNull); + expect(linuxInfo.buildId, isNull); + expect(linuxInfo.variant, isNull); + expect(linuxInfo.variantId, isNull); + }), skip: !Platform.isLinux); + + testWidgets('Check all Windows info values are available', + ((WidgetTester tester) async { + expect( + windowsInfo.numberOfCores, + isPositive, + ); + expect( + windowsInfo.computerName, + isNotEmpty, + ); + expect( + windowsInfo.systemMemoryInMegabytes, + isPositive, + ); + expect( + windowsInfo.userName, + isNotEmpty, + ); + expect( + windowsInfo.majorVersion, + equals(10), + ); + expect( + windowsInfo.minorVersion, + equals(0), + ); + expect( + windowsInfo.buildNumber, + greaterThan(10240), + ); + expect( + windowsInfo.platformId, + equals(2), + ); + expect( + windowsInfo.reserved, + isZero, + ); + expect( + windowsInfo.buildLab, + isNotEmpty, + ); + expect( + windowsInfo.buildLab, + startsWith( + windowsInfo.buildNumber.toString(), + ), + ); + expect( + windowsInfo.buildLabEx, + isNotEmpty, + ); + expect( + windowsInfo.buildLab, + startsWith(windowsInfo.buildNumber.toString()), + ); + expect( + windowsInfo.digitalProductId, + isNotEmpty, + ); + expect( + windowsInfo.editionId, + isNotEmpty, + ); + expect( + windowsInfo.productId, + isNotEmpty, + ); + expect( + RegExp(r'^([A-Z0-9]{5}-){4}[A-Z0-9]{5}$') + .hasMatch(windowsInfo.productId) || + RegExp(r'^([A-Z0-9]{5}-){3}[A-Z0-9]{5}$') + .hasMatch(windowsInfo.productId), + isTrue, + ); + expect( + windowsInfo.productName, + isNotEmpty, + ); + expect( + windowsInfo.productName, + startsWith('Windows'), + ); + expect( + windowsInfo.releaseId, + isNotEmpty, + ); + expect( + windowsInfo.deviceId, + isNotEmpty, + ); + }), skip: !Platform.isWindows); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100755 index 00000000..8c6e5614 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Debug.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Debug.xcconfig new file mode 100755 index 00000000..ec97fc6f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Release.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Release.xcconfig new file mode 100755 index 00000000..c4855bfe --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..075d8eec --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,723 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 429829504B428B91CD34394A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E34A4006F430DB1C5A018A69 /* Pods_Runner.framework */; }; + 5DA2260ADE5F76F3FFB815A0 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CDBB1B1CAFCC61F3647887B /* Pods_RunnerTests.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0CDBB1B1CAFCC61F3647887B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 6FDE560C1C66BB7D507C271F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 70B46233CBC827D9357CAED6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B3E39AFFADC3FF84A14CEAD9 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + B5226E28C7B6DFA3F85A5F86 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + CC560B6DE1FF1FA91F20AF89 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + E34A4006F430DB1C5A018A69 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F7BF1F60B00C1E3390715BB3 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 479820A9DCB23F89315408D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5DA2260ADE5F76F3FFB815A0 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 429829504B428B91CD34394A /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2A76172809353E74F0878C8F /* Frameworks */ = { + isa = PBXGroup; + children = ( + E34A4006F430DB1C5A018A69 /* Pods_Runner.framework */, + 0CDBB1B1CAFCC61F3647887B /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + EE25C9049E007CD6D24A97DF /* Pods */, + 2A76172809353E74F0878C8F /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + EE25C9049E007CD6D24A97DF /* Pods */ = { + isa = PBXGroup; + children = ( + 6FDE560C1C66BB7D507C271F /* Pods-Runner.debug.xcconfig */, + 70B46233CBC827D9357CAED6 /* Pods-Runner.release.xcconfig */, + B5226E28C7B6DFA3F85A5F86 /* Pods-Runner.profile.xcconfig */, + B3E39AFFADC3FF84A14CEAD9 /* Pods-RunnerTests.debug.xcconfig */, + CC560B6DE1FF1FA91F20AF89 /* Pods-RunnerTests.release.xcconfig */, + F7BF1F60B00C1E3390715BB3 /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + AC296610EEC611E8563F8C04 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 479820A9DCB23F89315408D4 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + F83E525764739090E301A316 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 4FD9CA2815573411DDA641D3 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 4FD9CA2815573411DDA641D3 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + AC296610EEC611E8563F8C04 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + F83E525764739090E301A316 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B3E39AFFADC3FF84A14CEAD9 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CC560B6DE1FF1FA91F20AF89 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F7BF1F60B00C1E3390715BB3 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..919434a6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..8e3ca5df --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/AppDelegate.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/AppDelegate.swift new file mode 100755 index 00000000..b6363034 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..d36b1fab --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100755 index 00000000..dc9ada47 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100755 index 00000000..7353c41e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100755 index 00000000..6ed2d933 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100755 index 00000000..4cd7b009 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100755 index 00000000..fe730945 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100755 index 00000000..321773cd Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100755 index 00000000..502f463a Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100755 index 00000000..e9f5fea2 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100755 index 00000000..84ac32ae Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100755 index 00000000..8953cba0 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100755 index 00000000..0467bf12 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100755 index 00000000..0bedcf2f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100755 index 00000000..89c2725b --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 00000000..f2e259c7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/Main.storyboard b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100755 index 00000000..f3c28516 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Info.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Info.plist new file mode 100755 index 00000000..c30f9332 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Device Info Plus + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + device_info_plus_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Runner-Bridging-Header.h b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Runner-Bridging-Header.h new file mode 100755 index 00000000..308a2a56 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/RunnerTests/RunnerTests.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..86a7c3b1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/lib/main.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/lib/main.dart new file mode 100755 index 00000000..24afdc09 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/lib/main.dart @@ -0,0 +1,269 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'dart:developer' as developer; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +void main() { + runZonedGuarded(() { + runApp(const MyApp()); + }, (dynamic error, dynamic stack) { + developer.log("Something went wrong!", error: error, stackTrace: stack); + }); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + static final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); + Map _deviceData = {}; + + @override + void initState() { + super.initState(); + initPlatformState(); + } + + Future initPlatformState() async { + var deviceData = {}; + + try { + if (kIsWeb) { + deviceData = _readWebBrowserInfo(await deviceInfoPlugin.webBrowserInfo); + } else { + deviceData = switch (defaultTargetPlatform) { + TargetPlatform.android => + _readAndroidBuildData(await deviceInfoPlugin.androidInfo), + TargetPlatform.iOS => + _readIosDeviceInfo(await deviceInfoPlugin.iosInfo), + TargetPlatform.linux => + _readLinuxDeviceInfo(await deviceInfoPlugin.linuxInfo), + TargetPlatform.windows => + _readWindowsDeviceInfo(await deviceInfoPlugin.windowsInfo), + TargetPlatform.macOS => + _readMacOsDeviceInfo(await deviceInfoPlugin.macOsInfo), + TargetPlatform.fuchsia => { + 'Error:': 'Fuchsia platform isn\'t supported' + }, + }; + } + } on PlatformException { + deviceData = { + 'Error:': 'Failed to get platform version.' + }; + } + + if (!mounted) return; + + setState(() { + _deviceData = deviceData; + }); + } + + Map _readAndroidBuildData(AndroidDeviceInfo build) { + return { + 'version.securityPatch': build.version.securityPatch, + 'version.sdkInt': build.version.sdkInt, + 'version.release': build.version.release, + 'version.previewSdkInt': build.version.previewSdkInt, + 'version.incremental': build.version.incremental, + 'version.codename': build.version.codename, + 'version.baseOS': build.version.baseOS, + 'board': build.board, + 'bootloader': build.bootloader, + 'brand': build.brand, + 'device': build.device, + 'display': build.display, + 'fingerprint': build.fingerprint, + 'hardware': build.hardware, + 'host': build.host, + 'id': build.id, + 'manufacturer': build.manufacturer, + 'model': build.model, + 'product': build.product, + 'name': build.name, + 'supported32BitAbis': build.supported32BitAbis, + 'supported64BitAbis': build.supported64BitAbis, + 'supportedAbis': build.supportedAbis, + 'tags': build.tags, + 'type': build.type, + 'isPhysicalDevice': build.isPhysicalDevice, + 'systemFeatures': build.systemFeatures, + 'serialNumber': build.serialNumber, + 'isLowRamDevice': build.isLowRamDevice, + }; + } + + Map _readIosDeviceInfo(IosDeviceInfo data) { + return { + 'name': data.name, + 'systemName': data.systemName, + 'systemVersion': data.systemVersion, + 'model': data.model, + 'modelName': data.modelName, + 'localizedModel': data.localizedModel, + 'identifierForVendor': data.identifierForVendor, + 'isPhysicalDevice': data.isPhysicalDevice, + 'isiOSAppOnMac': data.isiOSAppOnMac, + 'utsname.sysname:': data.utsname.sysname, + 'utsname.nodename:': data.utsname.nodename, + 'utsname.release:': data.utsname.release, + 'utsname.version:': data.utsname.version, + 'utsname.machine:': data.utsname.machine, + }; + } + + Map _readLinuxDeviceInfo(LinuxDeviceInfo data) { + return { + 'name': data.name, + 'version': data.version, + 'id': data.id, + 'idLike': data.idLike, + 'versionCodename': data.versionCodename, + 'versionId': data.versionId, + 'prettyName': data.prettyName, + 'buildId': data.buildId, + 'variant': data.variant, + 'variantId': data.variantId, + 'machineId': data.machineId, + }; + } + + Map _readWebBrowserInfo(WebBrowserInfo data) { + return { + 'browserName': data.browserName.name, + 'appCodeName': data.appCodeName, + 'appName': data.appName, + 'appVersion': data.appVersion, + 'deviceMemory': data.deviceMemory, + 'language': data.language, + 'languages': data.languages, + 'platform': data.platform, + 'product': data.product, + 'productSub': data.productSub, + 'userAgent': data.userAgent, + 'vendor': data.vendor, + 'vendorSub': data.vendorSub, + 'hardwareConcurrency': data.hardwareConcurrency, + 'maxTouchPoints': data.maxTouchPoints, + }; + } + + Map _readMacOsDeviceInfo(MacOsDeviceInfo data) { + return { + 'computerName': data.computerName, + 'hostName': data.hostName, + 'arch': data.arch, + 'model': data.model, + 'modelName': data.modelName, + 'kernelVersion': data.kernelVersion, + 'majorVersion': data.majorVersion, + 'minorVersion': data.minorVersion, + 'patchVersion': data.patchVersion, + 'osRelease': data.osRelease, + 'activeCPUs': data.activeCPUs, + 'memorySize': data.memorySize, + 'cpuFrequency': data.cpuFrequency, + 'systemGUID': data.systemGUID, + }; + } + + Map _readWindowsDeviceInfo(WindowsDeviceInfo data) { + return { + 'numberOfCores': data.numberOfCores, + 'computerName': data.computerName, + 'systemMemoryInMegabytes': data.systemMemoryInMegabytes, + 'userName': data.userName, + 'majorVersion': data.majorVersion, + 'minorVersion': data.minorVersion, + 'buildNumber': data.buildNumber, + 'platformId': data.platformId, + 'csdVersion': data.csdVersion, + 'servicePackMajor': data.servicePackMajor, + 'servicePackMinor': data.servicePackMinor, + 'suitMask': data.suitMask, + 'productType': data.productType, + 'reserved': data.reserved, + 'buildLab': data.buildLab, + 'buildLabEx': data.buildLabEx, + 'digitalProductId': data.digitalProductId, + 'displayVersion': data.displayVersion, + 'editionId': data.editionId, + 'installDate': data.installDate, + 'productId': data.productId, + 'productName': data.productName, + 'registeredOwner': data.registeredOwner, + 'releaseId': data.releaseId, + 'deviceId': data.deviceId, + }; + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ThemeData( + useMaterial3: true, + colorSchemeSeed: const Color(0x9f4376f8), + ), + home: Scaffold( + appBar: AppBar( + title: Text(_getAppBarTitle()), + elevation: 4, + ), + body: ListView( + children: _deviceData.keys.map( + (String property) { + return Row( + children: [ + Container( + padding: const EdgeInsets.all(10), + child: Text( + property, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + ), + Expanded( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Text( + '${_deviceData[property]}', + maxLines: 10, + overflow: TextOverflow.ellipsis, + ), + ), + ), + ], + ); + }, + ).toList(), + ), + ), + ); + } + + String _getAppBarTitle() => kIsWeb + ? 'Web Browser info' + : switch (defaultTargetPlatform) { + TargetPlatform.android => 'Android Device Info', + TargetPlatform.iOS => 'iOS Device Info', + TargetPlatform.linux => 'Linux Device Info', + TargetPlatform.windows => 'Windows Device Info', + TargetPlatform.macOS => 'MacOS Device Info', + TargetPlatform.fuchsia => 'Fuchsia Device Info', + }; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/CMakeLists.txt new file mode 100755 index 00000000..fe30a3e6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "io.flutter.plugins.deviceinfoexample.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..5b465c7e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/main.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/main.cc new file mode 100755 index 00000000..8bc15615 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/main.cc @@ -0,0 +1,11 @@ +#include "my_application.h" + +int main(int argc, char **argv) { + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); + + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.cc new file mode 100755 index 00000000..cef2f771 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.cc @@ -0,0 +1,45 @@ +#include "my_application.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication *application) { + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +static void my_application_class_init(MyApplicationClass *klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; +} + +static void my_application_init(MyApplication *self) {} + +MyApplication *my_application_new() { + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.h b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.h new file mode 100755 index 00000000..3258a73c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication *my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Debug.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100755 index 00000000..4b81f9b2 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Release.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100755 index 00000000..5caa9d15 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..17738f85 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,791 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 1330411FFFFCBD68C52506B9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F374CDA27EFCEFF13CF00643 /* Pods_Runner.framework */; }; + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + B32C194861AFDC5B38D41D89 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F061CD8A37C585748E94D972 /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 279B31026D7637D54DF99D75 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* example_device_info.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_device_info.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 7D5FF3AEF35298EDF0C1201D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + D768A5BD5BCBEE43226A64A7 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + D94DF7FF96C592E0D5C3E009 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + E07B0AE1E178661F8653244B /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + E92B0E6DF286F1A21B388CA1 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + F061CD8A37C585748E94D972 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F374CDA27EFCEFF13CF00643 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B32C194861AFDC5B38D41D89 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1330411FFFFCBD68C52506B9 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + C28D557964D09D46EC4A0164 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* example_device_info.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + C28D557964D09D46EC4A0164 /* Pods */ = { + isa = PBXGroup; + children = ( + E07B0AE1E178661F8653244B /* Pods-Runner.debug.xcconfig */, + 7D5FF3AEF35298EDF0C1201D /* Pods-Runner.release.xcconfig */, + D768A5BD5BCBEE43226A64A7 /* Pods-Runner.profile.xcconfig */, + D94DF7FF96C592E0D5C3E009 /* Pods-RunnerTests.debug.xcconfig */, + E92B0E6DF286F1A21B388CA1 /* Pods-RunnerTests.release.xcconfig */, + 279B31026D7637D54DF99D75 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + F374CDA27EFCEFF13CF00643 /* Pods_Runner.framework */, + F061CD8A37C585748E94D972 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 55412E34F2958028872E9D98 /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 88B27E32653C92A6BA8EB23C /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 5BEC5C74096CA740BAE5D11D /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* example_device_info.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 55412E34F2958028872E9D98 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 5BEC5C74096CA740BAE5D11D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 88B27E32653C92A6BA8EB23C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D94DF7FF96C592E0D5C3E009 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example_device_info.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example_device_info"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E92B0E6DF286F1A21B388CA1 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example_device_info.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example_device_info"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 279B31026D7637D54DF99D75 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example_device_info.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example_device_info"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..7bb1c7df --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/AppDelegate.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/AppDelegate.swift new file mode 100755 index 00000000..8e02df28 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..a2ec33f1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "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" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100755 index 00000000..82b6f9d9 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100755 index 00000000..13b35eba Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100755 index 00000000..0a3f5fa4 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100755 index 00000000..bdb57226 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100755 index 00000000..f083318e Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100755 index 00000000..326c0e72 Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100755 index 00000000..2f1632cf Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Base.lproj/MainMenu.xib b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100755 index 00000000..80e867a4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/AppInfo.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100755 index 00000000..af912343 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = device_info_plus_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.deviceinfoexample.example + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 io.flutter.plugins.deviceinfoexample. All rights reserved. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Debug.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Debug.xcconfig new file mode 100755 index 00000000..36b0fd94 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Release.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Release.xcconfig new file mode 100755 index 00000000..dff4f495 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Warnings.xcconfig b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100755 index 00000000..42bcbf47 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/DebugProfile.entitlements b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/DebugProfile.entitlements new file mode 100755 index 00000000..dddb8a30 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Info.plist b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Info.plist new file mode 100755 index 00000000..4789daa6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/MainFlutterWindow.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/MainFlutterWindow.swift new file mode 100755 index 00000000..3cc05eb2 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Release.entitlements b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Release.entitlements new file mode 100755 index 00000000..852fa1a4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/RunnerTests/RunnerTests.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..5418c9f5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/pubspec.yaml new file mode 100755 index 00000000..8d8200cf --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/pubspec.yaml @@ -0,0 +1,25 @@ +name: device_info_plus_example +description: Demonstrates how to use the device_info_plus plugin. + +dependencies: + flutter: + sdk: flutter + device_info_plus: ^11.3.0 + +dev_dependencies: + flutter_driver: + sdk: flutter + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + flutter_lints: ">=4.0.0 <6.0.0" + +flutter: + uses-material-design: true + +environment: + sdk: '>=3.4.0 <4.0.0' + flutter: '>=3.22.0' + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/favicon.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/favicon.png new file mode 100755 index 00000000..8aaa46ac Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/favicon.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-192.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-192.png new file mode 100755 index 00000000..b749bfef Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-192.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-512.png b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-512.png new file mode 100755 index 00000000..88cfd48d Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-512.png differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/index.html b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/index.html new file mode 100755 index 00000000..99eacb28 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/index.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + example + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/manifest.json b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/manifest.json new file mode 100755 index 00000000..8c012917 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/CMakeLists.txt new file mode 100755 index 00000000..abf90408 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.15) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..b02c5485 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..977e38b5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/Runner.rc b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/Runner.rc new file mode 100755 index 00000000..13f98c0a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "io.flutter.plugins.deviceinfoexample" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 io.flutter.plugins.deviceinfoexample. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..0f0105d9 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.cpp @@ -0,0 +1,64 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opporutunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.h b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..69234d4f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.h @@ -0,0 +1,39 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "run_loop.h" +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { +public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + virtual ~FlutterWindow(); + +protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + +private: + // The run loop driving events for this window. + RunLoop *run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/main.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/main.cpp new file mode 100755 index 00000000..09895686 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/main.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resource.h b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resources/app_icon.ico b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resources/app_icon.ico differ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.cpp new file mode 100755 index 00000000..31b89f62 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.cpp @@ -0,0 +1,66 @@ +#include "run_loop.h" + +#include + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto instance : flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.h b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.h new file mode 100755 index 00000000..7fe1aacc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.h @@ -0,0 +1,38 @@ +#ifndef RUNNER_RUN_LOOP_H_ +#define RUNNER_RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { +public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const &) = delete; + RunLoop &operator=(RunLoop const &) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + +private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUNNER_RUN_LOOP_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/runner.exe.manifest b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.cpp new file mode 100755 index 00000000..7758aabf --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.cpp @@ -0,0 +1,63 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t *utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.h b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.h new file mode 100755 index 00000000..ff43ce2c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t *utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.cpp b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..90ff01e5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.cpp @@ -0,0 +1,237 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { +public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + +private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar *instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; + +const wchar_t *WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size) { + Destroy(); + + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window *that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.h b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.h new file mode 100755 index 00000000..7b518125 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.h @@ -0,0 +1,95 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { +public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus.podspec b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus.podspec new file mode 100755 index 00000000..6038dd29 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus.podspec @@ -0,0 +1,24 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'device_info_plus' + s.version = '0.0.1' + s.summary = 'Flutter Device Info Plus' + s.description = <<-DESC +Get current device information from within the Flutter application. +Downloaded by pub (not CocoaPods). + DESC + s.homepage = 'https://github.com/fluttercommunity/plus_plugins' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Community Team' => 'authors@fluttercommunity.dev' } + s.source = { :http => 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/device_info_plus' } + s.documentation_url = 'https://pub.dev/packages/device_info_plus' + s.source_files = 'device_info_plus/Sources/device_info_plus/**/*.{h,m}' + s.public_header_files = 'device_info_plus/Sources/device_info_plus/include/**/*.h' + s.dependency 'Flutter' + s.platform = :ios, '12.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.resource_bundles = {'device_info_plus_privacy' => ['device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy']} +end + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Package.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Package.swift new file mode 100755 index 00000000..a4defdd7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "device_info_plus", + platforms: [ + .iOS("12.0"), + ], + products: [ + .library(name: "device-info-plus", targets: ["device_info_plus"]) + ], + dependencies: [], + targets: [ + .target( + name: "device_info_plus", + dependencies: [], + resources: [ + .process("PrivacyInfo.xcprivacy"), + ], + cSettings: [ + .headerSearchPath("include/device_info_plus") + ] + ) + ] +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m new file mode 100755 index 00000000..cda41d95 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m @@ -0,0 +1,208 @@ +// +// DeviceIdentifiers.m +// device_info_plus +// +// Created by Volodymyr on 06.11.2024. +// +#import "./include/device_info_plus/DeviceIdentifiers.h" + +@implementation DeviceIdentifiers + ++ (NSString *)userKnownDeviceModel:(NSString *)identifier { + if ([identifier isEqualToString:@"iPhone6,1"]) { + return @"iPhone 5s"; + } else if ([identifier isEqualToString:@"iPhone6,2"]) { + return @"iPhone 5s"; + } else if ([identifier isEqualToString:@"iPhone7,2"]) { + return @"iPhone 6"; + } else if ([identifier isEqualToString:@"iPhone7,1"]) { + return @"iPhone 6 Plus"; + } else if ([identifier isEqualToString:@"iPhone8,1"]) { + return @"iPhone 6s"; + } else if ([identifier isEqualToString:@"iPhone8,2"]) { + return @"iPhone 6s Plus"; + } else if ([identifier isEqualToString:@"iPhone9,1"] || + [identifier isEqualToString:@"iPhone9,3"]) { + return @"iPhone 7"; + } else if ([identifier isEqualToString:@"iPhone9,2"] || + [identifier isEqualToString:@"iPhone9,4"]) { + return @"iPhone 7 Plus"; + } else if ([identifier isEqualToString:@"iPhone8,4"]) { + return @"iPhone SE"; + } else if ([identifier isEqualToString:@"iPhone10,1"] || + [identifier isEqualToString:@"iPhone10,4"]) { + return @"iPhone 8"; + } else if ([identifier isEqualToString:@"iPhone10,2"] || + [identifier isEqualToString:@"iPhone10,5"]) { + return @"iPhone 8 Plus"; + } else if ([identifier isEqualToString:@"iPhone10,3"] || + [identifier isEqualToString:@"iPhone10,6"]) { + return @"iPhone X"; + } else if ([identifier isEqualToString:@"iPhone11,2"]) { + return @"iPhone XS"; + } else if ([identifier isEqualToString:@"iPhone11,4"] || + [identifier isEqualToString:@"iPhone11,6"]) { + return @"iPhone XS Max"; + } else if ([identifier isEqualToString:@"iPhone11,8"]) { + return @"iPhone XR"; + } else if ([identifier isEqualToString:@"iPhone12,1"]) { + return @"iPhone 11"; + } else if ([identifier isEqualToString:@"iPhone12,3"]) { + return @"iPhone 11 Pro"; + } else if ([identifier isEqualToString:@"iPhone12,5"]) { + return @"iPhone 11 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone12,8"]) { + return @"iPhone SE 2"; + } else if ([identifier isEqualToString:@"iPhone13,2"]) { + return @"iPhone 12"; + } else if ([identifier isEqualToString:@"iPhone13,1"]) { + return @"iPhone 12 Mini"; + } else if ([identifier isEqualToString:@"iPhone13,3"]) { + return @"iPhone 12 Pro"; + } else if ([identifier isEqualToString:@"iPhone13,4"]) { + return @"iPhone 12 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone14,5"]) { + return @"iPhone 13"; + } else if ([identifier isEqualToString:@"iPhone14,4"]) { + return @"iPhone 13 Mini"; + } else if ([identifier isEqualToString:@"iPhone14,2"]) { + return @"iPhone 13 Pro"; + } else if ([identifier isEqualToString:@"iPhone14,3"]) { + return @"iPhone 13 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone14,6"]) { + return @"iPhone SE 3"; + } else if ([identifier isEqualToString:@"iPhone14,7"]) { + return @"iPhone 14"; + } else if ([identifier isEqualToString:@"iPhone14,8"]) { + return @"iPhone 14 Plus"; + } else if ([identifier isEqualToString:@"iPhone15,2"]) { + return @"iPhone 14 Pro"; + } else if ([identifier isEqualToString:@"iPhone15,3"]) { + return @"iPhone 14 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone15,4"]) { + return @"iPhone 15"; + } else if ([identifier isEqualToString:@"iPhone15,5"]) { + return @"iPhone 15 Plus"; + } else if ([identifier isEqualToString:@"iPhone16,1"]) { + return @"iPhone 15 Pro"; + } else if ([identifier isEqualToString:@"iPhone16,2"]) { + return @"iPhone 15 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone17,3"]) { + return @"iPhone 16"; + } else if ([identifier isEqualToString:@"iPhone17,4"]) { + return @"iPhone 16 Plus"; + } else if ([identifier isEqualToString:@"iPhone17,1"]) { + return @"iPhone 16 Pro"; + } else if ([identifier isEqualToString:@"iPhone17,2"]) { + return @"iPhone 16 Pro Max"; + // iPads + } else if ([identifier isEqualToString:@"iPad4,1"] || + [identifier isEqualToString:@"iPad4,2"] || + [identifier isEqualToString:@"iPad4,3"]) { + return @"iPad Air"; + } else if ([identifier isEqualToString:@"iPad5,3"] || + [identifier isEqualToString:@"iPad5,4"]) { + return @"iPad Air 2"; + } else if ([identifier isEqualToString:@"iPad6,11"] || + [identifier isEqualToString:@"iPad6,12"]) { + return @"iPad 5"; + } else if ([identifier isEqualToString:@"iPad7,5"] || + [identifier isEqualToString:@"iPad7,6"]) { + return @"iPad 6"; + } else if ([identifier isEqualToString:@"iPad11,3"] || + [identifier isEqualToString:@"iPad11,4"]) { + return @"iPad Air 3"; + } else if ([identifier isEqualToString:@"iPad7,11"] || + [identifier isEqualToString:@"iPad7,12"]) { + return @"iPad 7"; + } else if ([identifier isEqualToString:@"iPad11,6"] || + [identifier isEqualToString:@"iPad11,7"]) { + return @"iPad 8"; + } else if ([identifier isEqualToString:@"iPad12,1"] || + [identifier isEqualToString:@"iPad12,2"]) { + return @"iPad 9"; + } else if ([identifier isEqualToString:@"iPad13,18"] || + [identifier isEqualToString:@"iPad13,19"]) { + return @"iPad 10"; + } else if ([identifier isEqualToString:@"iPad13,1"] || + [identifier isEqualToString:@"iPad13,2"]) { + return @"iPad Air 4"; + } else if ([identifier isEqualToString:@"iPad13,16"] || + [identifier isEqualToString:@"iPad13,17"]) { + return @"iPad Air 5"; + } else if ([identifier isEqualToString:@"iPad14,8"] || + [identifier isEqualToString:@"iPad14,9"]) { + return @"iPad Air 11-Inch M2"; + } else if ([identifier isEqualToString:@"iPad14,10"] || + [identifier isEqualToString:@"iPad14,11"]) { + return @"iPad Air 13-Inch M2"; + } else if ([identifier isEqualToString:@"iPad2,5"] || + [identifier isEqualToString:@"iPad2,6"] || + [identifier isEqualToString:@"iPad2,7"]) { + return @"iPad Mini"; + } else if ([identifier isEqualToString:@"iPad4,4"] || + [identifier isEqualToString:@"iPad4,5"] || + [identifier isEqualToString:@"iPad4,6"]) { + return @"iPad Mini 2"; + } else if ([identifier isEqualToString:@"iPad4,7"] || + [identifier isEqualToString:@"iPad4,8"] || + [identifier isEqualToString:@"iPad4,9"]) { + return @"iPad Mini 3"; + } else if ([identifier isEqualToString:@"iPad5,1"] || + [identifier isEqualToString:@"iPad5,2"]) { + return @"iPad Mini 4"; + } else if ([identifier isEqualToString:@"iPad11,1"] || + [identifier isEqualToString:@"iPad11,2"]) { + return @"iPad Mini 5"; + } else if ([identifier isEqualToString:@"iPad14,1"] || + [identifier isEqualToString:@"iPad14,2"]) { + return @"iPad Mini 6"; + } else if ([identifier isEqualToString:@"iPad6,3"] || + [identifier isEqualToString:@"iPad6,4"]) { + return @"iPad Pro 9-Inch"; + } else if ([identifier isEqualToString:@"iPad6,7"] || + [identifier isEqualToString:@"iPad6,8"]) { + return @"iPad Pro 12-Inch"; + } else if ([identifier isEqualToString:@"iPad7,1"] || [identifier isEqualToString:@"iPad7,2"]) { + return @"iPad Pro 12-Inch 2"; + } else if ([identifier isEqualToString:@"iPad7,3"] || [identifier isEqualToString:@"iPad7,4"]) { + return @"iPad Pro 10-Inch"; + } else if ([identifier isEqualToString:@"iPad8,1"] || [identifier isEqualToString:@"iPad8,2"] || + [identifier isEqualToString:@"iPad8,3"] || [identifier isEqualToString:@"iPad8,4"]) { + return @"iPad Pro 11-Inch"; + } else if ([identifier isEqualToString:@"iPad8,5"] || [identifier isEqualToString:@"iPad8,6"] || + [identifier isEqualToString:@"iPad8,7"] || [identifier isEqualToString:@"iPad8,8"]) { + return @"iPad Pro 12-Inch 3"; + } else if ([identifier isEqualToString:@"iPad8,9"] || + [identifier isEqualToString:@"iPad8,10"]) { + return @"iPad Pro 11-Inch 2"; + } else if ([identifier isEqualToString:@"iPad8,11"] || + [identifier isEqualToString:@"iPad8,12"]) { + return @"iPad Pro 12-Inch 4"; + } else if ([identifier isEqualToString:@"iPad13,4"] || + [identifier isEqualToString:@"iPad13,5"] || + [identifier isEqualToString:@"iPad13,6"] || + [identifier isEqualToString:@"iPad13,7"]) { + return @"iPad Pro 11-Inch 3"; + } else if ([identifier isEqualToString:@"iPad13,8"] || + [identifier isEqualToString:@"iPad13,9"] || + [identifier isEqualToString:@"iPad13,10"] || + [identifier isEqualToString:@"iPad13,11"]) { + return @"iPad Pro 12-Inch 5"; + } else if ([identifier isEqualToString:@"iPad14,3"] || + [identifier isEqualToString:@"iPad14,4"]) { + return @"iPad Pro 11-Inch 4"; + } else if ([identifier isEqualToString:@"iPad14,5"] || + [identifier isEqualToString:@"iPad14,6"]) { + return @"iPad Pro 12-Inch 6"; + } else if ([identifier isEqualToString:@"iPad16,3"] || + [identifier isEqualToString:@"iPad16,4"]) { + return @"iPad Pro 11-Inch (M4)"; + } else if ([identifier isEqualToString:@"iPad16,5"] || + [identifier isEqualToString:@"iPad16,6"]) { + return @"iPad Pro 13-Inch (M4)"; + } else { + return @"Unknown device"; + } +} +@end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m new file mode 100755 index 00000000..2b495c7c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m @@ -0,0 +1,77 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "./include/device_info_plus/FPPDeviceInfoPlusPlugin.h" +#import "./include/device_info_plus/DeviceIdentifiers.h" +#import + +@implementation FPPDeviceInfoPlusPlugin ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/device_info" + binaryMessenger:[registrar messenger]]; + FPPDeviceInfoPlusPlugin *instance = [[FPPDeviceInfoPlusPlugin alloc] init]; + [registrar addMethodCallDelegate:instance channel:channel]; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call + result:(FlutterResult)result { + if ([@"getDeviceInfo" isEqualToString:call.method]) { + UIDevice *device = [UIDevice currentDevice]; + struct utsname un; + uname(&un); + + NSNumber *isPhysicalNumber = + [NSNumber numberWithBool:[self isDevicePhysical]]; + NSProcessInfo *info = [NSProcessInfo processInfo]; + NSNumber *isiOSAppOnMac = [NSNumber numberWithBool:NO]; + if (@available(iOS 14.0, *)) { + isiOSAppOnMac = [NSNumber numberWithBool:[info isiOSAppOnMac]]; + } + NSString *machine; + NSString *deviceName; + if ([self isDevicePhysical]) { + machine = @(un.machine); + } else { + machine = [info environment][@"SIMULATOR_MODEL_IDENTIFIER"]; + } + deviceName = [DeviceIdentifiers userKnownDeviceModel:machine]; + + result(@{ + @"name" : [device name], + @"systemName" : [device systemName], + @"systemVersion" : [device systemVersion], + @"model" : [device model], + @"localizedModel" : [device localizedModel], + @"modelName" : deviceName, + @"identifierForVendor" : [[device identifierForVendor] UUIDString] + ?: [NSNull null], + @"isPhysicalDevice" : isPhysicalNumber, + @"isiOSAppOnMac" : isiOSAppOnMac, + @"utsname" : @{ + @"sysname" : @(un.sysname), + @"nodename" : @(un.nodename), + @"release" : @(un.release), + @"version" : @(un.version), + @"machine" : machine, + } + }); + } else { + result(FlutterMethodNotImplemented); + } +} + +// return value is false if code is run on a simulator +- (BOOL)isDevicePhysical { + BOOL isPhysicalDevice = NO; +#if TARGET_OS_SIMULATOR + isPhysicalDevice = NO; +#else + isPhysicalDevice = YES; +#endif + + return isPhysicalDevice; +} + +@end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy new file mode 100755 index 00000000..a34b7e2e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/DeviceIdentifiers.h b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/DeviceIdentifiers.h new file mode 100755 index 00000000..0f5c8d70 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/DeviceIdentifiers.h @@ -0,0 +1,13 @@ +// +// DeviceIdentifiers.h +// device_info_plus +// +// Created by Volodymyr on 06.11.2024. +// +#import + +@interface DeviceIdentifiers : NSObject + ++ (NSString *)userKnownDeviceModel:(NSString *)identifier; + +@end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/FPPDeviceInfoPlusPlugin.h b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/FPPDeviceInfoPlusPlugin.h new file mode 100755 index 00000000..430e81ce --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/FPPDeviceInfoPlusPlugin.h @@ -0,0 +1,8 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface FPPDeviceInfoPlusPlugin : NSObject +@end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/device_info_plus.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/device_info_plus.dart new file mode 100755 index 00000000..38c83762 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/device_info_plus.dart @@ -0,0 +1,115 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:flutter/foundation.dart'; + +import 'src/model/android_device_info.dart'; +import 'src/model/ios_device_info.dart'; +import 'src/model/linux_device_info.dart'; +import 'src/model/macos_device_info.dart'; +import 'src/model/web_browser_info.dart'; +import 'src/model/windows_device_info.dart'; + +export 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart' + show BaseDeviceInfo; + +export 'src/model/android_device_info.dart'; +export 'src/model/ios_device_info.dart'; +export 'src/model/linux_device_info.dart'; +export 'src/model/macos_device_info.dart'; +export 'src/model/web_browser_info.dart'; +export 'src/model/windows_device_info.dart'; + +export 'src/device_info_plus_linux.dart' + if (dart.library.js_interop) 'src/device_info_plus_web.dart'; +export 'src/device_info_plus_windows.dart' + if (dart.library.js_interop) 'src/device_info_plus_web.dart'; + +/// Provides device and operating system information. +class DeviceInfoPlugin { + /// No work is done when instantiating the plugin. It's safe to call this + /// repeatedly or in performance-sensitive blocks. + DeviceInfoPlugin(); + + // This is to manually endorse the Linux plugin until automatic registration + // of dart plugins is implemented. + // See https://github.com/flutter/flutter/issues/52267 for more details. + static DeviceInfoPlatform get _platform { + return DeviceInfoPlatform.instance; + } + + /// This information does not change from call to call. Cache it. + AndroidDeviceInfo? _cachedAndroidDeviceInfo; + + /// Information derived from `android.os.Build`. + /// + /// See: https://developer.android.com/reference/android/os/Build.html + Future get androidInfo async => + _cachedAndroidDeviceInfo ??= + AndroidDeviceInfo.fromMap((await _platform.deviceInfo()).data); + + /// This information does not change from call to call. Cache it. + IosDeviceInfo? _cachedIosDeviceInfo; + + /// Information derived from `UIDevice`. + /// + /// See: https://developer.apple.com/documentation/uikit/uidevice + Future get iosInfo async => _cachedIosDeviceInfo ??= + IosDeviceInfo.fromMap((await _platform.deviceInfo()).data); + + /// This information does not change from call to call. Cache it. + LinuxDeviceInfo? _cachedLinuxDeviceInfo; + + /// Information derived from `/etc/os-release`. + /// + /// See: https://www.freedesktop.org/software/systemd/man/os-release.html + Future get linuxInfo async => _cachedLinuxDeviceInfo ??= + await _platform.deviceInfo() as LinuxDeviceInfo; + + /// This information does not change from call to call. Cache it. + WebBrowserInfo? _cachedWebBrowserInfo; + + /// Information derived from `Navigator`. + Future get webBrowserInfo async => + _cachedWebBrowserInfo ??= await _platform.deviceInfo() as WebBrowserInfo; + + /// This information does not change from call to call. Cache it. + MacOsDeviceInfo? _cachedMacosDeviceInfo; + + /// Returns device information for macos. Information sourced from Sysctl. + Future get macOsInfo async => _cachedMacosDeviceInfo ??= + MacOsDeviceInfo.fromMap((await _platform.deviceInfo()).data); + + WindowsDeviceInfo? _cachedWindowsDeviceInfo; + + /// Returns device information for Windows. + Future get windowsInfo async => + _cachedWindowsDeviceInfo ??= + await _platform.deviceInfo() as WindowsDeviceInfo; + + /// Returns device information for the current platform. + Future get deviceInfo async { + if (kIsWeb) { + return webBrowserInfo; + } else { + if (Platform.isAndroid) { + return androidInfo; + } else if (Platform.isIOS) { + return iosInfo; + } else if (Platform.isLinux) { + return linuxInfo; + } else if (Platform.isMacOS) { + return macOsInfo; + } else if (Platform.isWindows) { + return windowsInfo; + } + } + // allow for extension of the plugin + return _platform.deviceInfo(); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_linux.dart new file mode 100755 index 00000000..95ab8eac --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_linux.dart @@ -0,0 +1,104 @@ +import 'dart:async'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:file/file.dart'; +import 'package:file/local.dart'; +import 'package:meta/meta.dart'; + +/// See [DeviceInfoPlatform] +class DeviceInfoPlusLinuxPlugin extends DeviceInfoPlatform { + /// Register this dart class as the platform implementation for linux + static void registerWith() { + DeviceInfoPlatform.instance = DeviceInfoPlusLinuxPlugin(); + } + + LinuxDeviceInfo? _cache; + final FileSystem _fileSystem; + + /// + DeviceInfoPlusLinuxPlugin({@visibleForTesting FileSystem? fileSystem}) + : _fileSystem = fileSystem ?? const LocalFileSystem(); + + @override + Future deviceInfo() async { + return _cache ??= await _getInfo(); + } + + Future linuxInfo() async { + return (await deviceInfo()) as LinuxDeviceInfo; + } + + Future _getInfo() async { + final os = await _getOsRelease() ?? {}; + final lsb = await _getLsbRelease() ?? {}; + final machineId = await _getMachineId(); + + return LinuxDeviceInfo( + name: os['NAME'] ?? 'Linux', + version: os['VERSION'] ?? lsb['LSB_VERSION'], + id: os['ID'] ?? lsb['DISTRIB_ID'] ?? 'linux', + idLike: os['ID_LIKE']?.split(' '), + versionCodename: os['VERSION_CODENAME'] ?? lsb['DISTRIB_CODENAME'], + versionId: os['VERSION_ID'] ?? lsb['DISTRIB_RELEASE'], + prettyName: os['PRETTY_NAME'] ?? lsb['DISTRIB_DESCRIPTION'] ?? 'Linux', + buildId: os['BUILD_ID'], + variant: os['VARIANT'], + variantId: os['VARIANT_ID'], + machineId: machineId, + ); + } + + Future?> _getOsRelease() { + return _tryReadKeyValues('/etc/os-release').then((value) async => + value ?? await _tryReadKeyValues('/usr/lib/os-release')); + } + + Future?> _getLsbRelease() { + return _tryReadKeyValues('/etc/lsb-release'); + } + + Future _getMachineId() { + return _tryReadValue('/etc/machine-id'); + } + + Future _tryReadValue(String path) { + return _fileSystem + .file(path) + .readAsString() + .then((str) => str.trim(), onError: (_) => null); + } + + Future?> _tryReadKeyValues(String path) { + return _fileSystem + .file(path) + .readAsLines() + .then((lines) => lines.toKeyValues(), onError: (_) => null); + } +} + +extension _Unquote on String { + String removePrefix(String prefix) { + if (!startsWith(prefix)) return this; + return substring(prefix.length); + } + + String removeSuffix(String suffix) { + if (!endsWith(suffix)) return this; + return substring(0, length - suffix.length); + } + + String unquote() { + return removePrefix('"').removeSuffix('"'); + } +} + +extension _KeyValues on List { + Map toKeyValues() { + return Map.fromEntries(map((line) { + final parts = line.split('='); + if (parts.length != 2) return MapEntry(line, null); + return MapEntry(parts.first, parts.last.unquote()); + })); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_macos.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_macos.dart new file mode 100755 index 00000000..39e7bb81 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_macos.dart @@ -0,0 +1,2 @@ +// ignore: dangling_library_doc_comments +/// The platform interface handles the method channel calls. This file exists to silence errors on pub. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_web.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_web.dart new file mode 100755 index 00000000..30f5727c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_web.dart @@ -0,0 +1,60 @@ +import 'dart:async'; +import 'dart:js_interop'; +import 'package:web/web.dart' as html show window, Navigator; + +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +import 'model/web_browser_info.dart'; + +/// The web implementation of the BatteryPlusPlatform of the BatteryPlus plugin. +class DeviceInfoPlusWebPlugin extends DeviceInfoPlatform { + /// Constructs a DeviceInfoPlusPlugin. + DeviceInfoPlusWebPlugin(navigator) : _navigator = navigator; + + final html.Navigator _navigator; + + /// Factory method that initializes the DeviceInfoPlus plugin platform + /// with an instance of the plugin for the web. + static void registerWith(Registrar registrar) { + DeviceInfoPlatform.instance = + DeviceInfoPlusWebPlugin(html.window.navigator); + } + + @override + Future deviceInfo() { + return Future.value( + WebBrowserInfo.fromMap( + { + 'appCodeName': _navigator.appCodeName, + 'appName': _navigator.appName, + 'appVersion': _navigator.appVersion, + 'deviceMemory': _navigator.safeDeviceMemory, + 'language': _navigator.language, + 'languages': _navigator.languages.toDart, + 'platform': _navigator.platform, + 'product': _navigator.product, + 'productSub': _navigator.productSub, + 'userAgent': _navigator.userAgent, + 'vendor': _navigator.vendor, + 'vendorSub': _navigator.vendorSub, + 'hardwareConcurrency': _navigator.hardwareConcurrency, + 'maxTouchPoints': _navigator.maxTouchPoints, + }, + ), + ); + } +} + +/// Some Navigator properties are not fully supported in all browsers. +/// However, package:web does not provide a safe way to access these properties, +/// and assumes they are always not null. +/// +/// This extension provides a safe way to access these properties. +/// +/// See: https://github.com/dart-lang/web/issues/326 +/// https://github.com/fluttercommunity/plus_plugins/issues/3391 +extension SafeNavigationGetterExtensions on html.Navigator { + @JS('deviceMemory') + external double? get safeDeviceMemory; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_windows.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_windows.dart new file mode 100755 index 00000000..213a0b8f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_windows.dart @@ -0,0 +1,180 @@ +/// The Windows implementation of `device_info_plus`. +library device_info_plus_windows; + +import 'dart:ffi'; +import 'dart:typed_data'; +import 'dart:developer' as developer; + +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:ffi/ffi.dart'; +import 'package:meta/meta.dart'; +import 'package:win32/win32.dart'; +import 'package:win32_registry/win32_registry.dart'; + +import 'model/windows_device_info.dart'; + +/// The Windows implementation of [DeviceInfoPlatform]. +class DeviceInfoPlusWindowsPlugin extends DeviceInfoPlatform { + /// Register this dart class as the platform implementation for windows + static void registerWith() { + DeviceInfoPlatform.instance = DeviceInfoPlusWindowsPlugin(); + } + + WindowsDeviceInfo? _cache; + + // In a well-meaning but somewhat misguided attempt to reduce apps from using + // version numbers for feature detection, most version number APIs don't give + // expected results on Windows 8 and above. RtlGetVersion is reliable and + // stable, but as a kernel API is documented in the Windows DDK (Driver + // Development Kit), rather than the SDK. As such, it's not included in + // package:win32, so we have to manually define it here. + // + // ignore: non_constant_identifier_names + void Function(Pointer) RtlGetVersion = + DynamicLibrary.open('ntdll.dll').lookupFunction< + Void Function(Pointer), + void Function(Pointer)>('RtlGetVersion'); + + /// Returns a [WindowsDeviceInfo] with information about the device. + @override + Future deviceInfo() { + return Future.value(_cache ??= getInfo()); + } + + @visibleForTesting + WindowsDeviceInfo getInfo() { + final systemInfo = calloc(); + final osVersionInfo = calloc() + ..ref.dwOSVersionInfoSize = sizeOf(); + + try { + final currentVersionKey = Registry.openPath(RegistryHive.localMachine, + path: r'SOFTWARE\Microsoft\Windows NT\CurrentVersion'); + final buildLab = currentVersionKey.getValueAsString('BuildLab') ?? ''; + final buildLabEx = currentVersionKey.getValueAsString('BuildLabEx') ?? ''; + final digitalProductIdValue = + currentVersionKey.getValue('DigitalProductId'); + final digitalProductId = digitalProductIdValue != null && + digitalProductIdValue.data is Uint8List + ? digitalProductIdValue.data as Uint8List + : Uint8List.fromList([]); + final displayVersion = + currentVersionKey.getValueAsString('DisplayVersion') ?? ''; + final editionId = currentVersionKey.getValueAsString('EditionID') ?? ''; + final installDate = DateTime.fromMillisecondsSinceEpoch( + 1000 * (currentVersionKey.getValueAsInt('InstallDate') ?? 0)); + final productId = currentVersionKey.getValueAsString('ProductID') ?? ''; + var productName = currentVersionKey.getValueAsString('ProductName') ?? ''; + final registeredOwner = + currentVersionKey.getValueAsString('RegisteredOwner') ?? ''; + final releaseId = currentVersionKey.getValueAsString('ReleaseId') ?? ''; + + final sqmClientKey = Registry.openPath(RegistryHive.localMachine, + path: r'SOFTWARE\Microsoft\SQMClient'); + final machineId = sqmClientKey.getValueAsString('MachineId') ?? ''; + + GetSystemInfo(systemInfo); + + // Use `RtlGetVersion` from `ntdll.dll` to get the Windows version. + RtlGetVersion(osVersionInfo); + + // Handle [productName] for Windows 11 separately (as per Raymond Chen's comment). + // https://stackoverflow.com/questions/69460588/how-can-i-find-the-windows-product-name-in-windows-11 + if (osVersionInfo.ref.dwBuildNumber >= 22000) { + productName = productName.replaceAll('10', '11'); + } + final data = WindowsDeviceInfo( + numberOfCores: systemInfo.ref.dwNumberOfProcessors, + computerName: getComputerName(), + systemMemoryInMegabytes: getSystemMemoryInMegabytes(), + userName: getUserName(), + majorVersion: osVersionInfo.ref.dwMajorVersion, + minorVersion: osVersionInfo.ref.dwMinorVersion, + buildNumber: osVersionInfo.ref.dwBuildNumber, + platformId: osVersionInfo.ref.dwPlatformId, + csdVersion: osVersionInfo.ref.szCSDVersion, + servicePackMajor: osVersionInfo.ref.wServicePackMajor, + servicePackMinor: osVersionInfo.ref.wServicePackMinor, + suitMask: osVersionInfo.ref.wSuiteMask, + productType: osVersionInfo.ref.wProductType, + reserved: osVersionInfo.ref.wReserved, + buildLab: buildLab, + buildLabEx: buildLabEx, + digitalProductId: digitalProductId, + displayVersion: displayVersion, + editionId: editionId, + installDate: installDate, + productId: productId, + productName: productName, + registeredOwner: registeredOwner, + releaseId: releaseId, + deviceId: machineId, + ); + return data; + } finally { + free(systemInfo); + free(osVersionInfo); + } + } + + @visibleForTesting + int getSystemMemoryInMegabytes() { + final memoryInKilobytes = calloc(); + try { + final result = GetPhysicallyInstalledSystemMemory(memoryInKilobytes); + if (result != 0) { + return memoryInKilobytes.value ~/ 1024; + } else { + developer.log('Failed to get system memory', error: GetLastError()); + return 0; + } + } finally { + free(memoryInKilobytes); + } + } + + @visibleForTesting + String getComputerName() { + // We call this a first time to get the length of the string in characters, + // so we can allocate sufficient memory. + final nSize = calloc(); + GetComputerNameEx( + COMPUTER_NAME_FORMAT.ComputerNameDnsFullyQualified, nullptr, nSize); + + // Now allocate memory for a native string and call this a second time. + final lpBuffer = wsalloc(nSize.value); + try { + final result = GetComputerNameEx( + COMPUTER_NAME_FORMAT.ComputerNameDnsFullyQualified, lpBuffer, nSize); + + if (result != 0) { + return lpBuffer.toDartString(); + } else { + developer.log('Failed to get computer name', error: GetLastError()); + return ""; + } + } finally { + free(lpBuffer); + free(nSize); + } + } + + @visibleForTesting + String getUserName() { + const maxLength = 256; // defined as UNLEN in Lmcons.h + final lpBuffer = wsalloc(maxLength + 1); // allow for terminating null + final pcbBuffer = calloc()..value = maxLength + 1; + try { + final result = GetUserName(lpBuffer, pcbBuffer); + if (result != 0) { + return lpBuffer.toDartString(); + } else { + developer.log('Failed to get user name', error: GetLastError()); + return ""; + } + } finally { + free(pcbBuffer); + free(lpBuffer); + } + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/android_device_info.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/android_device_info.dart new file mode 100755 index 00000000..d14c8c59 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/android_device_info.dart @@ -0,0 +1,253 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Information derived from `android.os.Build`. +/// +/// See: https://developer.android.com/reference/android/os/Build.html +class AndroidDeviceInfo extends BaseDeviceInfo { + AndroidDeviceInfo._({ + required Map data, + required this.version, + required this.board, + required this.bootloader, + required this.brand, + required this.device, + required this.display, + required this.fingerprint, + required this.hardware, + required this.host, + required this.id, + required this.manufacturer, + required this.model, + required this.product, + required this.name, + required List supported32BitAbis, + required List supported64BitAbis, + required List supportedAbis, + required this.tags, + required this.type, + required this.isPhysicalDevice, + required List systemFeatures, + required this.serialNumber, + required this.isLowRamDevice, + }) : supported32BitAbis = List.unmodifiable(supported32BitAbis), + supported64BitAbis = List.unmodifiable(supported64BitAbis), + supportedAbis = List.unmodifiable(supportedAbis), + systemFeatures = List.unmodifiable(systemFeatures), + super(data); + + /// Android operating system version values derived from `android.os.Build.VERSION`. + final AndroidBuildVersion version; + + /// The name of the underlying board, like "goldfish". + /// https://developer.android.com/reference/android/os/Build#BOARD + final String board; + + /// The system bootloader version number. + /// https://developer.android.com/reference/android/os/Build#BOOTLOADER + final String bootloader; + + /// The consumer-visible brand with which the product/hardware will be associated, if any. + /// https://developer.android.com/reference/android/os/Build#BRAND + final String brand; + + /// The name of the industrial design. + /// https://developer.android.com/reference/android/os/Build#DEVICE + final String device; + + /// A build ID string meant for displaying to the user. + /// https://developer.android.com/reference/android/os/Build#DISPLAY + final String display; + + /// A string that uniquely identifies this build. + /// https://developer.android.com/reference/android/os/Build#FINGERPRINT + final String fingerprint; + + /// The name of the hardware (from the kernel command line or /proc). + /// https://developer.android.com/reference/android/os/Build#HARDWARE + final String hardware; + + /// Hostname. + /// https://developer.android.com/reference/android/os/Build#HOST + final String host; + + /// Either a changelist number, or a label like "M4-rc20". + /// https://developer.android.com/reference/android/os/Build#ID + final String id; + + /// The manufacturer of the product/hardware. + /// https://developer.android.com/reference/android/os/Build#MANUFACTURER + final String manufacturer; + + /// The end-user-visible name for the end product. + /// https://developer.android.com/reference/android/os/Build#MODEL + final String model; + + /// The name of the overall product. + /// https://developer.android.com/reference/android/os/Build#PRODUCT + final String product; + + /// The name of the device. + /// https://developer.android.com/reference/android/provider/Settings.Global#DEVICE_NAME + final String name; + + /// An ordered list of 32 bit ABIs supported by this device. + /// Available only on Android L (API 21) and newer + /// https://developer.android.com/reference/android/os/Build#SUPPORTED_32_BIT_ABIS + final List supported32BitAbis; + + /// An ordered list of 64 bit ABIs supported by this device. + /// Available only on Android L (API 21) and newer + /// https://developer.android.com/reference/android/os/Build#SUPPORTED_64_BIT_ABIS + final List supported64BitAbis; + + /// An ordered list of ABIs supported by this device. + /// Available only on Android L (API 21) and newer + /// https://developer.android.com/reference/android/os/Build#SUPPORTED_ABIS + final List supportedAbis; + + /// Comma-separated tags describing the build, like "unsigned,debug". + /// https://developer.android.com/reference/android/os/Build#TAGS + final String tags; + + /// The type of build, like "user" or "eng". + /// https://developer.android.com/reference/android/os/Build#TYPE + final String type; + + /// `false` if the application is running in an emulator, `true` otherwise. + final bool isPhysicalDevice; + + /// Describes what features are available on the current device. + /// + /// This can be used to check if the device has, for example, a front-facing + /// camera, or a touchscreen. However, in many cases this is not the best + /// API to use. For example, if you are interested in bluetooth, this API + /// can tell you if the device has a bluetooth radio, but it cannot tell you + /// if bluetooth is currently enabled, or if you have been granted the + /// necessary permissions to use it. Please *only* use this if there is no + /// other way to determine if a feature is supported. + /// + /// This data comes from Android's PackageManager.getSystemAvailableFeatures, + /// and many of the common feature strings to look for are available in + /// PackageManager's public documentation: + /// https://developer.android.com/reference/android/content/pm/PackageManager + final List systemFeatures; + + /// Hardware serial number of the device, if available + /// + /// There are special restrictions on this identifier, more info here: + /// https://developer.android.com/reference/android/os/Build#getSerial() + final String serialNumber; + + /// `true` if the application is running on a low-RAM device, `false` otherwise. + final bool isLowRamDevice; + + /// Deserializes from the message received from [_kChannel]. + static AndroidDeviceInfo fromMap(Map map) { + return AndroidDeviceInfo._( + data: map, + version: AndroidBuildVersion._fromMap( + map['version']?.cast() ?? {}), + board: map['board'], + bootloader: map['bootloader'], + brand: map['brand'], + device: map['device'], + display: map['display'], + fingerprint: map['fingerprint'], + hardware: map['hardware'], + host: map['host'], + id: map['id'], + manufacturer: map['manufacturer'], + model: map['model'], + product: map['product'], + name: map['name'] ?? '', + supported32BitAbis: _fromList(map['supported32BitAbis'] ?? []), + supported64BitAbis: _fromList(map['supported64BitAbis'] ?? []), + supportedAbis: _fromList(map['supportedAbis'] ?? []), + tags: map['tags'], + type: map['type'], + isPhysicalDevice: map['isPhysicalDevice'], + systemFeatures: _fromList(map['systemFeatures'] ?? []), + serialNumber: map['serialNumber'], + isLowRamDevice: map['isLowRamDevice'], + ); + } + + /// Deserializes message as List + static List _fromList(List message) { + final list = message.takeWhile((item) => item != null).toList(); + return List.from(list); + } +} + +/// Version values of the current Android operating system build derived from +/// `android.os.Build.VERSION`. +/// +/// See: https://developer.android.com/reference/android/os/Build.VERSION.html +class AndroidBuildVersion { + const AndroidBuildVersion._({ + this.baseOS, + required this.codename, + required this.incremental, + required this.previewSdkInt, + required this.release, + required this.sdkInt, + this.securityPatch, + }); + + /// The base OS build the product is based on. + /// Available only on Android M (API 23) and newer + final String? baseOS; + + /// The current development codename, or the string "REL" if this is a release build. + final String codename; + + /// The internal value used by the underlying source control to represent this build. + /// Available only on Android M (API 23) and newer + final String incremental; + + /// The developer preview revision of a pre-release SDK. + final int? previewSdkInt; + + /// The user-visible version string. + final String release; + + /// The user-visible SDK version of the framework. + /// + /// Possible values are defined in: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html + final int sdkInt; + + /// The user-visible security patch level. + /// Available only on Android M (API 23) and newer + final String? securityPatch; + + /// Serializes [ AndroidBuildVersion ] to map. + @Deprecated('[toMap] method will be discontinued') + Map toMap() { + return { + 'baseOS': baseOS, + 'sdkInt': sdkInt, + 'release': release, + 'codename': codename, + 'incremental': incremental, + 'previewSdkInt': previewSdkInt, + 'securityPatch': securityPatch, + }; + } + + /// Deserializes from the map message received from [_kChannel]. + static AndroidBuildVersion _fromMap(Map map) { + return AndroidBuildVersion._( + baseOS: map['baseOS'], + codename: map['codename'], + incremental: map['incremental'], + previewSdkInt: map['previewSdkInt'], + release: map['release'], + sdkInt: map['sdkInt'], + securityPatch: map['securityPatch'], + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/ios_device_info.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/ios_device_info.dart new file mode 100755 index 00000000..aaf654a7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/ios_device_info.dart @@ -0,0 +1,123 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Information derived from `UIDevice`. +/// +/// See: https://developer.apple.com/documentation/uikit/uidevice +class IosDeviceInfo extends BaseDeviceInfo { + /// IOS device info class. + IosDeviceInfo._({ + required Map data, + required this.name, + required this.systemName, + required this.systemVersion, + required this.model, + required this.modelName, + required this.localizedModel, + this.identifierForVendor, + required this.isPhysicalDevice, + required this.isiOSAppOnMac, + required this.utsname, + }) : super(data); + + /// Device name. + /// + /// On iOS < 16 returns user-assigned device name + /// On iOS >= 16 returns a generic device name if project has + /// no entitlement to get user-assigned device name. + /// https://developer.apple.com/documentation/uikit/uidevice/1620015-name + final String name; + + /// The name of the current operating system. + /// https://developer.apple.com/documentation/uikit/uidevice/1620054-systemname + final String systemName; + + /// The current operating system version. + /// https://developer.apple.com/documentation/uikit/uidevice/1620043-systemversion + final String systemVersion; + + /// Device model according to OS + /// https://developer.apple.com/documentation/uikit/uidevice/1620044-model + final String model; + + /// Commercial or user-known model name + /// Examples: `iPhone 16 Pro`, `iPad Pro 11-Inch 3` + final String modelName; + + /// Localized name of the device model. + /// https://developer.apple.com/documentation/uikit/uidevice/1620029-localizedmodel + final String localizedModel; + + /// Unique UUID value identifying the current device. + /// https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor + final String? identifierForVendor; + + /// `false` if the application is running in a simulator, `true` otherwise. + final bool isPhysicalDevice; + + /// that indicates whether the process is an iPhone or iPad app running on a Mac. + /// https://developer.apple.com/documentation/foundation/nsprocessinfo/3608556-iosapponmac + final bool isiOSAppOnMac; + + /// Operating system information derived from `sys/utsname.h`. + final IosUtsname utsname; + + /// Deserializes from the map message received from [_kChannel]. + static IosDeviceInfo fromMap(Map map) { + return IosDeviceInfo._( + data: map, + name: map['name'], + systemName: map['systemName'], + systemVersion: map['systemVersion'], + model: map['model'], + modelName: map['modelName'], + localizedModel: map['localizedModel'], + identifierForVendor: map['identifierForVendor'], + isPhysicalDevice: map['isPhysicalDevice'], + isiOSAppOnMac: map['isiOSAppOnMac'], + utsname: + IosUtsname._fromMap(map['utsname']?.cast() ?? {}), + ); + } +} + +/// Information derived from `utsname`. +/// See http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysutsname.h.html for details. +class IosUtsname { + const IosUtsname._({ + required this.sysname, + required this.nodename, + required this.release, + required this.version, + required this.machine, + }); + + /// Operating system name. + final String sysname; + + /// Network node name. + final String nodename; + + /// Release level. + final String release; + + /// Version level. + final String version; + + /// Hardware type (e.g. 'iPhone7,1' for iPhone 6 Plus). + final String machine; + + /// Deserializes from the map message received from [_kChannel]. + static IosUtsname _fromMap(Map map) { + return IosUtsname._( + sysname: map['sysname'], + nodename: map['nodename'], + release: map['release'], + version: map['version'], + machine: map['machine'], + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/linux_device_info.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/linux_device_info.dart new file mode 100755 index 00000000..f7aa1088 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/linux_device_info.dart @@ -0,0 +1,168 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Device information for a Linux system. +/// +/// See: +/// - https://www.freedesktop.org/software/systemd/man/os-release.html +/// - https://www.freedesktop.org/software/systemd/man/machine-id.html +class LinuxDeviceInfo implements BaseDeviceInfo { + /// Constructs a LinuxDeviceInfo. + LinuxDeviceInfo({ + required this.name, + this.version, + required this.id, + this.idLike, + this.versionCodename, + this.versionId, + required this.prettyName, + this.buildId, + this.variant, + this.variantId, + required this.machineId, + }); + + /// A string identifying the operating system, without a version component, + /// and suitable for presentation to the user. + /// + /// Examples: 'Fedora', 'Debian GNU/Linux'. + /// + /// If not set, defaults to 'Linux'. + final String name; + + /// A string identifying the operating system version, excluding any OS name + /// information, possibly including a release code name, and suitable for + /// presentation to the user. + /// + /// Examples: '17', '17 (Beefy Miracle)'. + /// + /// This field is optional and may be null on some systems. + final String? version; + + /// A lower-case string identifying the operating system, excluding any + /// version information and suitable for processing by scripts or usage in + /// generated filenames. + /// + /// The ID contains no spaces or other characters outside of 0–9, a–z, '.', + /// '_' and '-'. + /// + /// Examples: 'fedora', 'debian'. + /// + /// If not set, defaults to 'linux'. + final String id; + + /// A space-separated list of operating system identifiers in the same syntax + /// as the [id] value. It lists identifiers of operating systems that are + /// closely related to the local operating system in regards to packaging + /// and programming interfaces, for example listing one or more OS identifiers + /// the local OS is a derivative from. + /// + /// Examples: an operating system with [id] 'centos', would list 'rhel' and + /// 'fedora', and an operating system with [id] 'ubuntu' would list 'debian'. + /// + /// This field is optional and may be null on some systems. + final List? idLike; + + /// A lower-case string identifying the operating system release code name, + /// excluding any OS name information or release version, and suitable for + /// processing by scripts or usage in generated filenames. + /// + /// The codename contains no spaces or other characters outside of 0–9, a–z, + /// '.', '_' and '-'. + /// + /// Examples: 'buster', 'xenial'. + /// + /// This field is optional and may be null on some systems. + final String? versionCodename; + + /// A lower-case string identifying the operating system version, excluding + /// any OS name information or release code name, and suitable for processing + /// by scripts or usage in generated filenames. + /// + /// The version is mostly numeric, and contains no spaces or other characters + /// outside of 0–9, a–z, '.', '_' and '-'. + /// + /// Examples: '17', '11.04'. + /// + /// This field is optional and may be null on some systems. + final String? versionId; + + /// A pretty operating system name in a format suitable for presentation to + /// the user. May or may not contain a release code name or OS version of some + /// kind, as suitable. + /// + /// Examples: 'Fedora 17 (Beefy Miracle)'. + /// + /// If not set, defaults to 'Linux'. + final String prettyName; + + /// A string uniquely identifying the system image used as the origin for a + /// distribution (it is not updated with system updates). The field can be + /// identical between different [versionId]s as `buildId` is an only a unique + /// identifier to a specific version. + /// + /// Examples: '2013-03-20.3', '201303203'. + /// + /// This field is optional and may be null on some systems. + final String? buildId; + + /// A string identifying a specific variant or edition of the operating system + /// suitable for presentation to the user. This field may be used to inform + /// the user that the configuration of this system is subject to a specific + /// divergent set of rules or default configuration settings. + /// + /// Examples: 'Server Edition', 'Smart Refrigerator Edition'. + /// + /// Note: this field is for display purposes only. The [variantId] field + /// should be used for making programmatic decisions. + /// + /// This field is optional and may be null on some systems. + final String? variant; + + /// A lower-case string identifying a specific variant or edition of the + /// operating system. This may be interpreted in order to determine a + /// divergent default configuration. + /// + /// The variant ID contains no spaces or other characters outside of 0–9, a–z, + /// '.', '_' and '-'. + /// + /// Examples: 'server', 'embedded'. + /// + /// This field is optional and may be null on some systems. + final String? variantId; + + /// A unique machine ID of the local system that is set during installation or + /// boot. The machine ID is hexadecimal, 32-character, lowercase ID. When + /// decoded from hexadecimal, this corresponds to a 16-byte/128-bit value. + final String? machineId; + + @override + // ignore: deprecated_member_use_from_same_package + Map get data => toMap(); + + @Deprecated('Use [data] getter instead') + @override + Map toMap() { + return { + 'name': name, + 'version': version, + 'id': id, + 'idLike': idLike, + 'versionCodename': versionCodename, + 'versionId': versionId, + 'prettyName': prettyName, + 'buildId': buildId, + 'variant': variant, + 'variantId': variantId, + 'machineId': machineId, + }; + } + + @override + String toString() { + return 'LinuxDeviceInfo(name: $name, version: $version, id: $id, idLike: $idLike, versionCodename: $versionCodename, versionId: $versionId, prettyName: $prettyName, buildId: $buildId, variant: $variant, variantId: $variantId, machineId: $machineId)'; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/macos_device_info.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/macos_device_info.dart new file mode 100755 index 00000000..7725c5d1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/macos_device_info.dart @@ -0,0 +1,97 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Object encapsulating MACOS device information. +class MacOsDeviceInfo extends BaseDeviceInfo { + /// Constructs a MacOsDeviceInfo. + MacOsDeviceInfo._({ + required Map data, + required this.computerName, + required this.hostName, + required this.arch, + required this.model, + required this.modelName, + required this.kernelVersion, + required this.osRelease, + required this.majorVersion, + required this.minorVersion, + required this.patchVersion, + required this.activeCPUs, + required this.memorySize, + required this.cpuFrequency, + required this.systemGUID, + }) : super(data); + + /// Name given to the local machine. + final String computerName; + + /// Operating system type + final String hostName; + + /// Machine cpu architecture + /// Note, that on Apple Silicon Macs can return `x86_64` if app runs via Rosetta + final String arch; + + /// Device model identifier + /// Examples: `MacBookPro18,3`, `Mac16,2`. + final String model; + + /// Device model name + /// Examples: `MacBook Pro (16-inch, 2021)`, `iMac (24-inch, 2024)`. + final String modelName; + + /// Machine Kernel version. + /// Examples: + /// `Darwin Kernel Version 15.3.0: Thu Dec 10 18:40:58 PST 2015; root:xnu-3248.30.4~1/RELEASE_X86_64` + /// or + /// `Darwin Kernel Version 15.0.0: Wed Dec 9 22:19:38 PST 2015; root:xnu-3248.31.3~2/RELEASE_ARM64_S8000` + final String kernelVersion; + + /// Operating system release number + final String osRelease; + + /// The major release number, such as 10 in version 10.9.3. + final int majorVersion; + + /// The minor release number, such as 9 in version 10.9.3. + final int minorVersion; + + /// The update release number, such as 3 in version 10.9.3. + final int patchVersion; + + /// Number of active CPUs + final int activeCPUs; + + /// Machine's memory size + final int memorySize; + + /// Device CPU Frequency + final int cpuFrequency; + + /// Device GUID + final String? systemGUID; + + /// Constructs a [MacOsDeviceInfo] from a Map of dynamic. + static MacOsDeviceInfo fromMap(Map map) { + return MacOsDeviceInfo._( + data: map, + computerName: map['computerName'], + hostName: map['hostName'], + arch: map['arch'], + model: map['model'], + modelName: map['modelName'], + kernelVersion: map['kernelVersion'], + osRelease: map['osRelease'], + majorVersion: map['majorVersion'], + minorVersion: map['minorVersion'], + patchVersion: map['patchVersion'], + activeCPUs: map['activeCPUs'], + memorySize: map['memorySize'], + cpuFrequency: map['cpuFrequency'], + systemGUID: map['systemGUID'], + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/web_browser_info.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/web_browser_info.dart new file mode 100755 index 00000000..03fa7f83 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/web_browser_info.dart @@ -0,0 +1,188 @@ +// Copyright 2020 The Flutter Community Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// List of supported browsers +enum BrowserName { + /// Mozilla Firefox + firefox, + + /// Samsumg Internet Browser + samsungInternet, + + /// Opera Web Browser + opera, + + /// Microsoft Internet Explorer + msie, + + /// Microsoft Edge + edge, + + /// Google Chrome + chrome, + + /// Apple Safari + safari, + + /// Unknown web browser + unknown, +} + +/// Information derived from `navigator`. +/// +/// See: https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator +class WebBrowserInfo implements BaseDeviceInfo { + /// Web Browser info class. + WebBrowserInfo({ + required this.appCodeName, + required this.appName, + required this.appVersion, + required this.deviceMemory, + required this.language, + required this.languages, + required this.platform, + required this.product, + required this.productSub, + required this.userAgent, + required this.vendor, + required this.vendorSub, + required this.maxTouchPoints, + required this.hardwareConcurrency, + }); + + /// the name of the current browser. + BrowserName get browserName { + return _parseUserAgentToBrowserName(); + } + + /// the internal "code" name of the current browser. + /// Note: Do not rely on this property to return the correct value. + final String? appCodeName; + + /// a DOMString with the official name of the browser. + /// Note: Do not rely on this property to return the correct value. + final String? appName; + + /// the version of the browser as a DOMString. + /// Note: Do not rely on this property to return the correct value. + final String? appVersion; + + /// the amount of device memory in gigabytes. This value is an approximation given by rounding to the nearest power of 2 and dividing that number by 1024. + final double? deviceMemory; + + /// a DOMString representing the preferred language of the user, usually the language of the browser UI. The null value is returned when this is unknown. + final String? language; + + /// an array of DOMString representing the languages known to the user, by order of preference. + final List? languages; + + /// the version of the browser as a DOMString. + /// Note: Do not rely on this property to return the correct value. + final String? platform; + + /// Always returns 'Gecko', on any browser. + /// Note: Do not rely on this property to return the correct value. + /// This property is kept only for compatibility purpose. + final String? product; + + /// the build number of the current browser + /// Note: Do not rely on this property to return the correct value. + final String? productSub; + + /// the build number of the current browser (e.g., "20060909") + final String? userAgent; + + /// the vendor name of the current browser + final String? vendor; + + /// Returns the vendor version number (e.g. "6.1") + /// Note: Do not rely on this property to return the correct value. + final String? vendorSub; + + /// the number of logical processor cores available. + final int? hardwareConcurrency; + + /// the maximum number of simultaneous touch contact points are supported by the current device. + final int? maxTouchPoints; + + /// Deserializes from the map message received from [Navigator]. + static WebBrowserInfo fromMap(Map map) { + return WebBrowserInfo( + appCodeName: map['appCodeName'], + appName: map['appName'], + appVersion: map['appVersion'], + deviceMemory: map['deviceMemory'], + language: map['language'], + languages: map['languages'], + platform: map['platform'], + product: map['product'], + productSub: map['productSub'], + userAgent: map['userAgent'], + vendor: map['vendor'], + vendorSub: map['vendorSub'], + hardwareConcurrency: map['hardwareConcurrency'], + maxTouchPoints: map['maxTouchPoints'], + ); + } + + @Deprecated('use [data] instead') + @override + Map toMap() { + return { + 'browserName': browserName, + 'appCodeName': appCodeName, + 'appName': appName, + 'appVersion': appVersion, + 'deviceMemory': deviceMemory, + 'language': language, + 'languages': languages, + 'platform': platform, + 'product': product, + 'productSub': productSub, + 'userAgent': userAgent, + 'vendor': vendor, + 'vendorSub': vendorSub, + 'hardwareConcurrency': hardwareConcurrency, + 'maxTouchPoints': maxTouchPoints, + }; + } + + BrowserName _parseUserAgentToBrowserName() { + final userAgent = this.userAgent; + if (userAgent == null) { + return BrowserName.unknown; + } else if (userAgent.contains('Firefox')) { + return BrowserName.firefox; + // "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0" + } else if (userAgent.contains('SamsungBrowser')) { + return BrowserName.samsungInternet; + // "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G955F Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/9.4 Chrome/67.0.3396.87 Mobile Safari/537.36 + } else if (userAgent.contains('Opera') || userAgent.contains('OPR')) { + return BrowserName.opera; + // "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 OPR/57.0.3098.106" + } else if (userAgent.contains('Trident')) { + return BrowserName.msie; + // "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; Zoom 3.6.0; wbx 1.0.0; rv:11.0) like Gecko" + } else if (userAgent.contains('Edg')) { + return BrowserName.edge; + // https://docs.microsoft.com/en-us/microsoft-edge/web-platform/user-agent-string + // "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.74 Safari/537.36 Edg/79.0.309.43" + // "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299" + } else if (userAgent.contains('Chrome')) { + return BrowserName.chrome; + // "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/66.0.3359.181 Chrome/66.0.3359.181 Safari/537.36" + } else if (userAgent.contains('Safari')) { + return BrowserName.safari; + // "Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1 980x1306" + } else { + return BrowserName.unknown; + } + } + + @override + // ignore: deprecated_member_use_from_same_package + Map get data => toMap(); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/windows_device_info.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/windows_device_info.dart new file mode 100755 index 00000000..d18037b7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/windows_device_info.dart @@ -0,0 +1,184 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Object encapsulating WINDOWS device information. +class WindowsDeviceInfo implements BaseDeviceInfo { + /// Constructs a [WindowsDeviceInfo]. + const WindowsDeviceInfo({ + required this.computerName, + required this.numberOfCores, + required this.systemMemoryInMegabytes, + required this.userName, + required this.majorVersion, + required this.minorVersion, + required this.buildNumber, + required this.platformId, + required this.csdVersion, + required this.servicePackMajor, + required this.servicePackMinor, + required this.suitMask, + required this.productType, + required this.reserved, + required this.buildLab, + required this.buildLabEx, + required this.digitalProductId, + required this.displayVersion, + required this.editionId, + required this.installDate, + required this.productId, + required this.productName, + required this.registeredOwner, + required this.releaseId, + required this.deviceId, + }); + + /// The computer's fully-qualified DNS name, where available. + final String computerName; + + /// Number of CPU cores on the local machine + final int numberOfCores; + + /// The physically installed memory in the computer. + /// This may not be the same as available memory. + final int systemMemoryInMegabytes; + + final String userName; + + /// The major version number of the operating system. + /// For example, for Windows 2000, the major version number is five. + /// For more information, see the table in Remarks. + /// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfoexw#remarks + final int majorVersion; + + /// The minor version number of the operating system. + /// For example, for Windows 2000, the minor version number is zero. + /// For more information, see the table in Remarks. + /// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfoexw#remarks + final int minorVersion; + + /// The build number of the operating system. + /// For example: + /// - `22000` or greater for Windows 11. + /// - `10240` or greator for Windows 10. + final int buildNumber; + + /// The operating system platform. For Win32 on NT-based operating systems, + /// RtlGetVersion returns the value `VER_PLATFORM_WIN32_NT`. + final int platformId; + + /// The service-pack version string. + /// + /// This member contains a string, such as "Service Pack 3", which indicates + /// the latest service pack installed on the system. + final String csdVersion; + + /// The major version number of the latest service pack installed on the system. + /// For example, for Service Pack 3, the major version number is three. If no + /// service pack has been installed, the value is zero. + final int servicePackMajor; + + /// The minor version number of the latest service pack installed on the + /// system. For example, for Service Pack 3, the minor version number is zero. + final int servicePackMinor; + + /// The product suites available on the system. + final int suitMask; + + /// The product type. This member contains additional information about the + /// system. + final int productType; + + /// Reserved for future use. + final int reserved; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\BuildLab` registry key. For example: + /// `22000.co_release.210604-1628`. + final String buildLab; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\BuildLabEx` registry key. For example: + /// `22000.1.amd64fre.co_release.210604-1628`. + final String buildLabEx; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\DigitalProductId` registry key. + final Uint8List digitalProductId; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\DisplayVersion` registry key. For example: `21H2`. + final String displayVersion; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\EditionID` registry key. + final String editionId; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\InstallDate` registry key. + final DateTime installDate; + + /// Displayed as "Product ID" in Windows Settings. Value of the + /// `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\ProductId` registry key. For example: + /// `00000-00000-0000-AAAAA`. + final String productId; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\ProductName` registry key. For example: `Windows 10 Home + /// Single Language`. + final String productName; + + /// Value of the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\RegisteredOwner` registry key. For example: `Microsoft + /// Corporation`. + final String registeredOwner; + + /// Value of the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\ReleaseId` registry key. For example: `1903`. + final String releaseId; + + /// Displayed as "Device ID" in Windows Settings. Value of + /// `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SQMClient\MachineId` registry key. + final String deviceId; + + @Deprecated('use [data] instead') + @override + Map toMap() { + return { + 'computerName': computerName, + 'numberOfCores': numberOfCores, + 'systemMemoryInMegabytes': systemMemoryInMegabytes, + 'userName': userName, + 'majorVersion': majorVersion, + 'minorVersion': minorVersion, + 'buildNumber': buildNumber, + 'platformId': platformId, + 'csdVersion': csdVersion, + 'servicePackMajor': servicePackMajor, + 'servicePackMinor': servicePackMinor, + 'suitMask': suitMask, + 'productType': productType, + 'reserved': reserved, + 'buildLab': buildLab, + 'buildLabEx': buildLabEx, + 'digitalProductId': digitalProductId, + 'displayVersion': displayVersion, + 'editionId': editionId, + 'installDate': installDate, + 'productId': productId, + 'productName': productName, + 'registeredOwner': registeredOwner, + 'releaseId': releaseId, + 'deviceId': deviceId, + }; + } + + @override + // ignore: deprecated_member_use_from_same_package + Map get data => toMap(); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus.podspec b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus.podspec new file mode 100755 index 00000000..a5031bea --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus.podspec @@ -0,0 +1,23 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'device_info_plus' + s.version = '0.0.1' + s.summary = 'No-op implementation of the macos device_info_plus to avoid build issues on macos' + s.description = <<-DESC + No-op implementation of the device_info_plus plugin to avoid build issues on macos. +https://github.com/flutter/flutter/issues/46618 + DESC + s.homepage = 'https://github.com/fluttercommunity/plus_plugins/tree/master/packages/device_info_plus' + s.license = { :file => '../LICENSE' } + s.author = { 'Flutter Community' => 'authors@fluttercommunity.dev' } + s.source = { :path => '.' } + s.source_files = 'device_info_plus/Sources/device_info_plus/**/*.swift' + s.public_header_files = 'device_info_plus/Sources/device_info_plus/**/*.h' + s.dependency 'FlutterMacOS' + + s.platform = :osx + s.osx.deployment_target = '10.14' + s.resource_bundles = {'device_info_plus_privacy' => ['device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy']} +end diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Package.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Package.swift new file mode 100755 index 00000000..9cd83e6e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Package.swift @@ -0,0 +1,24 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "device_info_plus", + platforms: [ + .macOS("10.14") + ], + products: [ + .library(name: "device-info-plus", targets: ["device_info_plus"]) + ], + dependencies: [], + targets: [ + .target( + name: "device_info_plus", + dependencies: [], + resources: [ + .process("PrivacyInfo.xcprivacy"), + ] + ) + ] +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/CwlSysctl.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/CwlSysctl.swift new file mode 100755 index 00000000..3f29e31c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/CwlSysctl.swift @@ -0,0 +1,152 @@ +// +// CwlSysctl.swift +// CwlUtils +// +// Created by Matt Gallagher on 2016/02/03. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +import Foundation + +/// A "static"-only namespace around a series of functions that operate on buffers returned from the `Darwin.sysctl` function +public struct Sysctl { + /// Possible errors. + public enum Error: Swift.Error { + case unknown + case malformedUTF8 + case invalidSize + case posixError(POSIXErrorCode) + } + + /// Access the raw data for an array of sysctl identifiers. + public static func data(for keys: [Int32]) throws -> [Int8] { + return try keys.withUnsafeBufferPointer() { keysPointer throws -> [Int8] in + // Preflight the request to get the required data size + var requiredSize = 0 + let preFlightResult = Darwin.sysctl(UnsafeMutablePointer(mutating: keysPointer.baseAddress), UInt32(keys.count), nil, &requiredSize, nil, 0) + if preFlightResult != 0 { + throw POSIXErrorCode(rawValue: errno).map { + return Error.posixError($0) + } ?? Error.unknown + } + + // Run the actual request with an appropriately sized array buffer + let data = Array(repeating: 0, count: requiredSize) + let result = data.withUnsafeBufferPointer() { dataBuffer -> Int32 in + return Darwin.sysctl(UnsafeMutablePointer(mutating: keysPointer.baseAddress), UInt32(keys.count), UnsafeMutableRawPointer(mutating: dataBuffer.baseAddress), &requiredSize, nil, 0) + } + if result != 0 { + throw POSIXErrorCode(rawValue: errno).map { Error.posixError($0) } ?? Error.unknown + } + + return data + } + } + + /// Convert a sysctl name string like "hw.memsize" to the array of `sysctl` identifiers (e.g. [CTL_HW, HW_MEMSIZE]) + public static func keys(for name: String) throws -> [Int32] { + var keysBufferSize = Int(CTL_MAXNAME) + var keysBuffer = Array(repeating: 0, count: keysBufferSize) + try keysBuffer.withUnsafeMutableBufferPointer { (lbp: inout UnsafeMutableBufferPointer) throws in + try name.withCString { (nbp: UnsafePointer) throws in + guard sysctlnametomib(nbp, lbp.baseAddress, &keysBufferSize) == 0 else { + throw POSIXErrorCode(rawValue: errno).map { Error.posixError($0) } ?? Error.unknown + } + } + } + if keysBuffer.count > keysBufferSize { + keysBuffer.removeSubrange(keysBufferSize..(ofType: T.Type, forKeys keys: [Int32]) throws -> T { + let buffer = try data(for: keys) + if buffer.count != MemoryLayout.size { + throw Error.invalidSize + } + return try buffer.withUnsafeBufferPointer() { bufferPtr throws -> T in + guard let baseAddress = bufferPtr.baseAddress else { throw Error.unknown } + return baseAddress.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee } + } + } + + /// Invoke `sysctl` with an array of identifers, interpreting the returned buffer as the specified type. This function will throw `Error.invalidSize` if the size of buffer returned from `sysctl` fails to match the size of `T`. + public static func value(ofType type: T.Type, forKeys keys: Int32...) throws -> T { + return try value(ofType: type, forKeys: keys) + } + + /// Invoke `sysctl` with the specified name, interpreting the returned buffer as the specified type. This function will throw `Error.invalidSize` if the size of buffer returned from `sysctl` fails to match the size of `T`. + public static func value(ofType type: T.Type, forName name: String) throws -> T { + return try value(ofType: type, forKeys: keys(for: name)) + } + + /// Invoke `sysctl` with an array of identifers, interpreting the returned buffer as a `String`. This function will throw `Error.malformedUTF8` if the buffer returned from `sysctl` cannot be interpreted as a UTF8 buffer. + public static func string(for keys: [Int32]) throws -> String { + let optionalString = try data(for: keys).withUnsafeBufferPointer() { dataPointer -> String? in + dataPointer.baseAddress.flatMap { String(validatingUTF8: $0) } + } + guard let s = optionalString else { + throw Error.malformedUTF8 + } + return s + } + + /// Invoke `sysctl` with an array of identifers, interpreting the returned buffer as a `String`. This function will throw `Error.malformedUTF8` if the buffer returned from `sysctl` cannot be interpreted as a UTF8 buffer. + public static func string(for keys: Int32...) throws -> String { + return try string(for: keys) + } + + /// Invoke `sysctl` with the specified name, interpreting the returned buffer as a `String`. This function will throw `Error.malformedUTF8` if the buffer returned from `sysctl` cannot be interpreted as a UTF8 buffer. + public static func string(for name: String) throws -> String { + return try string(for: keys(for: name)) + } + + /// e.g. "MyComputer.local" (from System Preferences -> Sharing -> Computer Name) + public static var hostName: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_HOSTNAME])) ?? "" } + + /// e.g. "x86_64" or "arm64" + public static var machine: String { return (try? Sysctl.string(for: [CTL_HW, HW_MACHINE])) ?? "" } + + /// e.g. "MacBookPro18,2" + public static var model: String { return (try? Sysctl.string(for: [CTL_HW, HW_MODEL])) ?? "" } + + /// e.g. "8" or "2" + public static var activeCPUs: Int32 { return (try? Sysctl.value(ofType: Int32.self, forKeys: [CTL_HW, HW_AVAILCPU])) ?? 0 } + + /// e.g. "15.3.0" or "15.0.0" + public static var osRelease: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_OSRELEASE])) ?? "" } + + /// e.g. "Darwin" or "Darwin" + public static var osType: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_OSTYPE])) ?? "" } + + /// e.g. "15D21" or "13D20" + public static var osVersion: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_OSVERSION])) ?? "" } + + /// e.g. "Darwin Kernel Version 15.3.0: Thu Dec 10 18:40:58 PST 2015; root:xnu-3248.30.4~1/RELEASE_X86_64" or + /// "Darwin Kernel Version 15.0.0: Wed Dec 9 22:19:38 PST 2015; root:xnu-3248.31.3~2/RELEASE_ARM64_S8000" + public static var version: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_VERSION])) ?? "" } + + #if os(macOS) + /// e.g. 199506 (not available on iOS) + public static var osRev: Int32 { return (try? Sysctl.value(ofType: Int32.self, forKeys: [CTL_KERN, KERN_OSREV])) ?? 0 } + + /// e.g. 2659000000 (not available on iOS) + public static var cpuFreq: Int64 { return (try? Sysctl.value(ofType: Int64.self, forName: "hw.cpufrequency")) ?? 0 } + + /// e.g. 25769803776 (not available on iOS) + public static var memSize: UInt64 { return (try? Sysctl.value(ofType: UInt64.self, forKeys: [CTL_HW, HW_MEMSIZE])) ?? 0 } + #endif +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.swift new file mode 100755 index 00000000..288808c1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.swift @@ -0,0 +1,99 @@ +import Foundation + +// Models list is taken from support.apple.com +// Example of the list with models https://support.apple.com/en-us/102869 + +func getMacModelName(modelNumber: String) -> String { + switch modelNumber { + // MacBook models (2015 and later) + case "MacBook8,1": return "MacBook (12-inch, 2015)" + case "MacBook9,1": return "MacBook (12-inch, 2016)" + case "MacBook10,1": return "MacBook (12-inch, 2017)" + + // MacBook Air models (2013 and later) + case "MacBookAir6,1": return "MacBook Air (11-inch, 2013)" + case "MacBookAir6,2": return "MacBook Air (13-inch, 2013)" + case "MacBookAir7,1": return "MacBook Air (11-inch, 2015)" + case "MacBookAir7,2": return "MacBook Air (13-inch, 2015-2017)" + case "MacBookAir8,1": return "MacBook Air (13-inch, 2018)" + case "MacBookAir8,2": return "MacBook Air (13-inch, 2019)" + case "MacBookAir9,1": return "MacBook Air (13-inch, 2020)" + case "MacBookAir10,1": return "MacBook Air (13-inch, 2020)" + case "Mac14,2": return "MacBook Air (13-inch, 2022)" + case "Mac14,15": return "MacBook Air (15-inch, 2023)" + case "Mac15,12": return "MacBook Air (13-inch, 2024)" + case "Mac15,13": return "MacBook Air (15-inch, 2024)" + + // MacBook Pro models (2012 and later) + case "MacBookPro10,1": return "MacBook Pro (15-inch, 2012-2013)" + case "MacBookPro10,2": return "MacBook Pro (13-inch, 2012-2013)" + case "MacBookPro11,1": return "MacBook Pro (13-inch, 2013-2014)" + case "MacBookPro11,2", "MacBookPro11,3": return "MacBook Pro (15-inch, 2013-2014)" + case "MacBookPro11,4", "MacBookPro11,5": return "MacBook Pro (15-inch, 2015)" + case "MacBookPro12,1": return "MacBook Pro (13-inch, 2015)" + case "MacBookPro13,1": return "MacBook Pro (13-inch, 2016)" + case "MacBookPro13,2": return "MacBook Pro (13-inch, 2016)" + case "MacBookPro13,3": return "MacBook Pro (15-inch, 2016)" + case "MacBookPro14,1": return "MacBook Pro (13-inch, 2017)" + case "MacBookPro14,2": return "MacBook Pro (13-inch, 2017)" + case "MacBookPro14,3": return "MacBook Pro (15-inch, 2017)" + case "MacBookPro15,1", "MacBookPro15,3": return "MacBook Pro (15-inch, 2018-2019)" + case "MacBookPro15,2": return "MacBook Pro (13-inch, 2018-2019)" + case "MacBookPro15,4": return "MacBook Pro (13-inch, 2019)" + case "MacBookPro16,1", "MacBookPro16,4": return "MacBook Pro (16-inch, 2019)" + case "MacBookPro16,2": return "MacBook Pro (13-inch, 2019)" + case "MacBookPro16,3": return "MacBook Pro (13-inch, 2020)" + case "MacBookPro17,1": return "MacBook Pro (13-inch, 2020)" + case "MacBookPro18,1": return "MacBook Pro (14-inch, 2021)" + case "MacBookPro18,2": return "MacBook Pro (16-inch, 2021)" + case "MacBookPro18,3": return "MacBook Pro (16-inch, 2021)" + case "Mac14,5", "Mac14,9": return "MacBook Pro (14-inch, 2023)" + case "Mac14,6", "Mac14,10": return "MacBook Pro (14-inch, 2023)" + case "Mac14,7": return "MacBook Pro (13-inch, 2022)" + case "Mac15,3": return "MacBook Pro (14-inch, 2023)" + case "Mac15,6", "Mac15,8", "Mac15.10": return "MacBook Pro (14-inch, 2023)" + case "Mac15,7", "Mac15,9", "Mac15.11": return "MacBook Pro (16-inch, 2023)" + + // iMac models (2013 and later) + case "iMac13,1": return "iMac (21.5-inch, 2013)" + case "iMac13,2": return "iMac (27-inch, 2013)" + case "iMac14,1": return "iMac (21.5-inch, 2014)" + case "iMac14,2": return "iMac (27-inch, 2014)" + case "iMac14,4": return "iMac (21.5-inch, 2014)" + case "iMac15,1": return "iMac (27-inch, 2014-2015)" + case "iMac16,1","iMac16,2": return "iMac (21.5-inch, 2015)" + case "iMac17,1": return "iMac (27-inch, 2015)" + case "iMac18,1": return "iMac (21.5-inch, 2017)" + case "iMac18,2": return "iMac (21.5-inch, 2017)" + case "iMac18,3": return "iMac (27-inch, 2017)" + case "iMac19,1": return "iMac (27-inch, 2019)" + case "iMac19,2": return "iMac (21.5-inch, 2019)" + case "iMac20,1", "iMac20,2": return "iMac (27-inch, 2020)" + case "iMac21,1", "iMac21,2": return "iMac (24-inch, 2021)" + case "Mac15,4", "Mac15,5": return "iMac (24-inch, 2023)" + case "Mac16,2", "Mac16,3": return "iMac (24-inch, 2024)" + + // Mac mini models (2012 and later) + case "MacMini6,1", "MacMini6,2": return "Mac mini (2012)" + case "MacMini7,1": return "Mac mini (2014)" + case "MacMini8,1": return "Mac mini (2018)" + case "MacMini9,1": return "Mac mini (2020)" + case "Mac14,12": return "Mac mini (2023)" + case "Mac14,3": return "Mac mini (2023)" + case "Mac16,15", "Mac16,10": return "Mac mini (2024)" + + // Mac Pro models (2013 and later) + case "MacPro6,1": return "Mac Pro (Late 2013)" + case "MacPro7,1": return "Mac Pro (2019)" + case "Mac14,8": return "Mac Pro (2023)" + + // iMac Pro + case "iMacPro1,1": return "iMac Pro (2017)" + + // Mac Studio (2022 and newer) + case "Mac13,1", "Mac13,2": return "Mac Studio (2022)" + case "Mac14,13", "Mac14,14": return "Mac Studio (2023)" + + default: return "Unknown Model" + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift new file mode 100755 index 00000000..a1f68236 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift @@ -0,0 +1,54 @@ +import Cocoa +import FlutterMacOS + +public class DeviceInfoPlusMacosPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "dev.fluttercommunity.plus/device_info", binaryMessenger: registrar.messenger) + let instance = DeviceInfoPlusMacosPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getDeviceInfo": + handleDeviceInfo(result: result) + default: + result(FlutterMethodNotImplemented) + } + } + + private func handleDeviceInfo(result: @escaping FlutterResult)-> Void{ + let computerName = Host.current().localizedName ?? Sysctl.hostName + let hostName = Sysctl.osType + let arch = Sysctl.machine + let model = Sysctl.model + let modelName = getMacModelName(modelNumber: Sysctl.model) + let kernelVersion = Sysctl.version + let osRelease = ProcessInfo.processInfo.operatingSystemVersionString + let osVersion = ProcessInfo.processInfo.operatingSystemVersion; + let majorVersion = osVersion.majorVersion + let minorVersion = osVersion.minorVersion + let patchVersion = osVersion.patchVersion + let activeCPUs = Sysctl.activeCPUs + let memorySize = Sysctl.memSize + let cpuFrequency = Sysctl.cpuFreq + let guid = SystemUUID.getSystemUUID() + + result([ + "computerName": computerName, + "hostName": hostName, + "arch": arch, + "model": model, + "modelName": modelName, + "kernelVersion": kernelVersion, + "osRelease": osRelease, + "majorVersion": majorVersion, + "minorVersion": minorVersion, + "patchVersion": patchVersion, + "activeCPUs": activeCPUs, + "memorySize": memorySize, + "cpuFrequency": cpuFrequency, + "systemGUID": guid + ] as [String: Any?]) + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy new file mode 100755 index 00000000..918d80be --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy @@ -0,0 +1,12 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/SystemUUID.swift b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/SystemUUID.swift new file mode 100755 index 00000000..0b93b221 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/SystemUUID.swift @@ -0,0 +1,23 @@ +import Foundation + +public struct SystemUUID { + + public static func getSystemUUID() -> String? { + let dev = IOServiceMatching("IOPlatformExpertDevice") + + var platformExpert: io_service_t + if #available(macOS 12, *) { + platformExpert = IOServiceGetMatchingService(kIOMainPortDefault, dev) + } else { + platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, dev) + } + + let serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert, kIOPlatformUUIDKey as CFString, kCFAllocatorDefault, 0) + IOObjectRelease(platformExpert) + let ser: CFTypeRef? = serialNumberAsCFString?.takeUnretainedValue() + if let result = ser as? String { + return result + } + return nil + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/pubspec.yaml new file mode 100755 index 00000000..717ca623 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/pubspec.yaml @@ -0,0 +1,53 @@ +name: device_info_plus +description: Flutter plugin providing detailed information about the device + (make, model, etc.), and Android or iOS version the app is running on. +version: 11.3.0 +homepage: https://github.com/fluttercommunity/plus_plugins +repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/device_info_plus/device_info_plus +issue_tracker: https://github.com/fluttercommunity/plus_plugins/labels/device_info_plus +topics: + - device + - information + - utils + +flutter: + plugin: + platforms: + android: + package: dev.fluttercommunity.plus.device_info + pluginClass: DeviceInfoPlusPlugin + ios: + pluginClass: FPPDeviceInfoPlusPlugin + linux: + dartPluginClass: DeviceInfoPlusLinuxPlugin + web: + pluginClass: DeviceInfoPlusWebPlugin + fileName: src/device_info_plus_web.dart + macos: + pluginClass: DeviceInfoPlusMacosPlugin + windows: + dartPluginClass: DeviceInfoPlusWindowsPlugin + +dependencies: + device_info_plus_platform_interface: ^7.0.2 + ffi: ^2.0.1 + file: ">=6.1.4 <8.0.0" + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + meta: ^1.8.0 + web: ^1.0.0 + win32: ^5.5.3 + win32_registry: ^1.1.0 + +dev_dependencies: + flutter_lints: ">=4.0.0 <6.0.0" + flutter_test: + sdk: flutter + mockito: ^5.4.0 + test: ^1.22.0 + +environment: + sdk: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_linux_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_linux_test.dart new file mode 100755 index 00000000..324de590 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_linux_test.dart @@ -0,0 +1,126 @@ +@TestOn('linux') +library device_info_plus_linux_test; + +import 'package:device_info_plus/src/device_info_plus_linux.dart'; +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:file/memory.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('registered instance', () { + DeviceInfoPlusLinuxPlugin.registerWith(); + expect(DeviceInfoPlatform.instance, isA()); + }); + test('os-release', () async { + final fs = MemoryFileSystem.test(); + final file = fs.file('/etc/os-release')..createSync(recursive: true); + file.writeAsStringSync(''' +NAME="A Linux" +VERSION="1.2.3 LTS (A Linux)" +ID=foo +ID_LIKE="bar baz" +VERSION_CODENAME=lts +VERSION_ID="1.2.3-lts" +PRETTY_NAME="A Linux 1.2.3 LTS" +BUILD_ID=1 +VARIANT="Community Edition" +VARIANT_ID=community +HOME_URL="https://www.fluttercommunity.dev/" + '''); + + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.name, equals('A Linux')); + expect(linuxInfo.version, equals('1.2.3 LTS (A Linux)')); + expect(linuxInfo.id, equals('foo')); + expect(linuxInfo.idLike, equals(['bar', 'baz'])); + expect(linuxInfo.versionCodename, equals('lts')); + expect(linuxInfo.versionId, equals('1.2.3-lts')); + expect(linuxInfo.prettyName, equals('A Linux 1.2.3 LTS')); + expect(linuxInfo.buildId, equals('1')); + expect(linuxInfo.variant, equals('Community Edition')); + expect(linuxInfo.variantId, equals('community')); + }); + + test('lsb-release', () async { + final fs = MemoryFileSystem.test(); + final file = fs.file('/etc/lsb-release')..createSync(recursive: true); + file.writeAsStringSync(''' +LSB_VERSION="LSB version" +DISTRIB_ID=distrib-id +DISTRIB_RELEASE=distrib-release +DISTRIB_CODENAME=distrib-codename +DISTRIB_DESCRIPTION="Distrib Description" + '''); + + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.name, equals('Linux')); + expect(linuxInfo.version, equals('LSB version')); + expect(linuxInfo.id, equals('distrib-id')); + expect(linuxInfo.idLike, isNull); + expect(linuxInfo.versionCodename, equals('distrib-codename')); + expect(linuxInfo.versionId, equals('distrib-release')); + expect(linuxInfo.prettyName, 'Distrib Description'); + expect(linuxInfo.buildId, isNull); + expect(linuxInfo.variant, isNull); + expect(linuxInfo.variantId, isNull); + }); + + test('precedence', () async { + final fs = MemoryFileSystem.test(); + final osFile = fs.file('/etc/os-release')..createSync(recursive: true); + osFile.writeAsStringSync(''' +VERSION="OS version" +ID=os + '''); + final lsbFile = fs.file('/etc/lsb-release')..createSync(recursive: true); + lsbFile.writeAsStringSync(''' +LSB_VERSION="LSB version" +DISTRIB_ID=lsb +DISTRIB_RELEASE=distrib-release +DISTRIB_CODENAME=distrib-codename +DISTRIB_DESCRIPTION="Distrib Description" + '''); + + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.name, equals('Linux')); + expect(linuxInfo.version, equals('OS version')); + expect(linuxInfo.id, equals('os')); + expect(linuxInfo.idLike, isNull); + expect(linuxInfo.versionCodename, equals('distrib-codename')); + expect(linuxInfo.versionId, equals('distrib-release')); + expect(linuxInfo.prettyName, 'Distrib Description'); + expect(linuxInfo.buildId, isNull); + expect(linuxInfo.variant, isNull); + expect(linuxInfo.variantId, isNull); + }); + + test('machine-id', () async { + final fs = MemoryFileSystem.test(); + final file = fs.file('/etc/machine-id')..createSync(recursive: true); + file.writeAsStringSync('machine-id'); + + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.machineId, equals('machine-id')); + }); + + test('missing files', () async { + final fs = MemoryFileSystem.test(); + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.name, equals('Linux')); + expect(linuxInfo.version, isNull); + expect(linuxInfo.id, equals('linux')); + expect(linuxInfo.idLike, isNull); + expect(linuxInfo.versionCodename, isNull); + expect(linuxInfo.versionId, isNull); + expect(linuxInfo.prettyName, 'Linux'); + expect(linuxInfo.buildId, isNull); + expect(linuxInfo.variant, isNull); + expect(linuxInfo.variantId, isNull); + expect(linuxInfo.machineId, isNull); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_web_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_web_test.dart new file mode 100755 index 00000000..b4ed2a4f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_web_test.dart @@ -0,0 +1,39 @@ +@TestOn('browser') +library device_info_plus_web_test; + +import 'package:device_info_plus/src/model/web_browser_info.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('WebBrowserInfo from Map with values', () { + final info = WebBrowserInfo.fromMap( + { + 'appCodeName': 'CODENAME', + 'appName': 'NAME', + 'appVersion': 'VERSION', + 'deviceMemory': 64, + 'language': 'en', + 'languages': ['en', 'es'], + 'platform': 'PLATFORM', + 'product': 'PRODUCT', + 'productSub': 'PRODUCTSUB', + 'userAgent': + 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0', + 'vendor': 'VENDOR', + 'vendorSub': 'VENDORSUB', + 'hardwareConcurrency': 1, + 'maxTouchPoints': 2, + }, + ); + + expect(info.appName, 'NAME'); + expect(info.browserName, BrowserName.firefox); + }); + + test('WebBrowserInfo from empty map', () { + final info = WebBrowserInfo.fromMap({}); + + expect(info.appName, isNull); + expect(info.browserName, BrowserName.unknown); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_windows_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_windows_test.dart new file mode 100755 index 00000000..c3a07ccd --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_windows_test.dart @@ -0,0 +1,86 @@ +@TestOn('windows') +library device_info_plus_windows_test; + +import 'dart:typed_data'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('registered instance', () { + DeviceInfoPlusWindowsPlugin.registerWith(); + expect(DeviceInfoPlatform.instance, isA()); + }); + test('system-memory-in-megabytes', () async { + final systemMemoryInMegabytes = + DeviceInfoPlusWindowsPlugin().getSystemMemoryInMegabytes(); + + // It's a reasonable expectation that any computer executing this test has + // >512MB RAM + expect(systemMemoryInMegabytes, greaterThan(512)); + }); + test('computer-name', () async { + final computerName = DeviceInfoPlusWindowsPlugin().getComputerName(); + // Must be a non-empty string value. + expect(computerName, isNotEmpty); + }); + test('user-name', () async { + final userName = DeviceInfoPlusWindowsPlugin().getUserName(); + // Must be a non-empty string value. + expect(userName, isNotEmpty); + }); + test('windows information', () async { + final deviceInfo = DeviceInfoPlusWindowsPlugin(); + final windowsInfo = (await deviceInfo.deviceInfo()) as WindowsDeviceInfo; + // Check whether windowsInfo.numberOfProcessors is a positive integer. + expect(windowsInfo.numberOfCores, isPositive); + // Check whether windowsInfo.computerName is a valid non-empty string. + expect(windowsInfo.computerName, isNotEmpty); + // Check whether windowsInfo.systemMemoryInMegabytes is an integer. + expect(windowsInfo.systemMemoryInMegabytes, isA()); + // Check whether windowsInfo.userName is a valid non-empty string. + expect(windowsInfo.userName, isNotEmpty); + // Check for Windows 10 or greater. + expect(windowsInfo.majorVersion, equals(10)); + expect(windowsInfo.minorVersion, equals(0)); + expect(windowsInfo.buildNumber, greaterThan(10240)); + // The value should always be 2 on Windows (VER_PLATFORM_WIN32_NT). + expect(windowsInfo.platformId, equals(2)); + // Check whether windowsInfo.reserved is zero. + expect(windowsInfo.reserved, isZero); + // Check whether windowsInfo.buildLab is a valid non-empty string & starts with windowsInfo.buildNumber. + expect(windowsInfo.buildLab, isNotEmpty); + expect( + windowsInfo.buildLab, + startsWith(windowsInfo.buildNumber.toString()), + ); + // Check whether windowsInfo.buildLabEx is a valid non-empty string & starts with windowsInfo.buildNumber. + expect(windowsInfo.buildLabEx, isNotEmpty); + expect( + windowsInfo.buildLab, + startsWith(windowsInfo.buildNumber.toString()), + ); + // Check whether windowsInfo.digitalProductId is a Uint8List. + expect(windowsInfo.digitalProductId, isA()); + expect(windowsInfo.digitalProductId, isNotEmpty); + // Check whether windowsInfo.editionId is a valid non-empty string. + expect(windowsInfo.editionId, isNotEmpty); + // Check whether windowsInfo.installDate is a valid date in the past. + expect(DateTime.now().isAfter(windowsInfo.installDate), isTrue); + // Check whether windowsInfo.productId is a valid non-empty string & matches 00000-00000-00000-AAAAA format. + expect(windowsInfo.productId, isNotEmpty); + expect( + windowsInfo.productId, + matches(RegExp(r'^([A-Z0-9]{5}-){3}[A-Z0-9]{5}$')), + ); + // Check whether windowsInfo.productName starts with "Windows". + expect(windowsInfo.productName, startsWith('Windows')); + // Check whether windowsInfo.registeredOwner is a valid non-empty string. + expect(windowsInfo.registeredOwner, isNotEmpty); + // Check whether windowsInfo.releaseId is a valid non-empty string. + expect(windowsInfo.releaseId, isNotEmpty); + // Check whether windowsInfo.deviceId is a valid non-empty string. + expect(windowsInfo.deviceId, isNotEmpty); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_fake.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_fake.dart new file mode 100755 index 00000000..46e53acd --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_fake.dart @@ -0,0 +1,42 @@ +part of '../model/android_device_info_test.dart'; + +const _fakeAndroidBuildVersion = { + 'sdkInt': 16, + 'baseOS': 'baseOS', + 'previewSdkInt': 30, + 'release': 'release', + 'codename': 'codename', + 'incremental': 'incremental', + 'securityPatch': 'securityPatch', +}; + +const _fakeSupportedAbis = ['arm64-v8a', 'x86', 'x86_64']; +const _fakeSupported32BitAbis = ['x86 (IA-32)', 'MMX']; +const _fakeSupported64BitAbis = ['x86-64', 'MMX', 'SSSE3']; +const _fakeSystemFeatures = ['FEATURE_AUDIO_PRO', 'FEATURE_AUDIO_OUTPUT']; + +const _fakeAndroidDeviceInfo = { + 'id': 'id', + 'host': 'host', + 'tags': 'tags', + 'type': 'type', + 'model': 'model', + 'board': 'board', + 'brand': 'Google', + 'device': 'device', + 'product': 'product', + "name": "Custom Device Name", + 'display': 'display', + 'hardware': 'hardware', + 'isPhysicalDevice': true, + 'bootloader': 'bootloader', + 'fingerprint': 'fingerprint', + 'manufacturer': 'manufacturer', + 'supportedAbis': _fakeSupportedAbis, + 'systemFeatures': _fakeSystemFeatures, + 'version': _fakeAndroidBuildVersion, + 'supported64BitAbis': _fakeSupported64BitAbis, + 'supported32BitAbis': _fakeSupported32BitAbis, + 'serialNumber': 'SERIAL', + 'isLowRamDevice': false, +}; diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_test.dart new file mode 100755 index 00000000..a5ab4e1e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_test.dart @@ -0,0 +1,52 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'package:device_info_plus/src/model/android_device_info.dart'; +import 'package:flutter_test/flutter_test.dart'; + +part '../model/android_device_info_fake.dart'; + +void main() { + group('$AndroidDeviceInfo fromMap | toMap', () { + test('fromMap should return $AndroidDeviceInfo with correct values', () { + final androidDeviceInfo = + AndroidDeviceInfo.fromMap(_fakeAndroidDeviceInfo); + + expect(androidDeviceInfo.id, 'id'); + expect(androidDeviceInfo.host, 'host'); + expect(androidDeviceInfo.tags, 'tags'); + expect(androidDeviceInfo.type, 'type'); + expect(androidDeviceInfo.model, 'model'); + expect(androidDeviceInfo.board, 'board'); + expect(androidDeviceInfo.brand, 'Google'); + expect(androidDeviceInfo.device, 'device'); + expect(androidDeviceInfo.product, 'product'); + expect(androidDeviceInfo.name, "Custom Device Name"); + expect(androidDeviceInfo.display, 'display'); + expect(androidDeviceInfo.hardware, 'hardware'); + expect(androidDeviceInfo.bootloader, 'bootloader'); + expect(androidDeviceInfo.isPhysicalDevice, isTrue); + expect(androidDeviceInfo.fingerprint, 'fingerprint'); + expect(androidDeviceInfo.manufacturer, 'manufacturer'); + expect(androidDeviceInfo.supportedAbis, _fakeSupportedAbis); + expect(androidDeviceInfo.systemFeatures, _fakeSystemFeatures); + expect(androidDeviceInfo.supported32BitAbis, _fakeSupported32BitAbis); + expect(androidDeviceInfo.supported64BitAbis, _fakeSupported64BitAbis); + expect(androidDeviceInfo.version.sdkInt, 16); + expect(androidDeviceInfo.version.baseOS, 'baseOS'); + expect(androidDeviceInfo.version.previewSdkInt, 30); + expect(androidDeviceInfo.version.release, 'release'); + expect(androidDeviceInfo.version.codename, 'codename'); + expect(androidDeviceInfo.version.incremental, 'incremental'); + expect(androidDeviceInfo.version.securityPatch, 'securityPatch'); + expect(androidDeviceInfo.serialNumber, 'SERIAL'); + expect(androidDeviceInfo.isLowRamDevice, false); + }); + + test('toMap should return map with correct key and map', () { + final androidDeviceInfo = + AndroidDeviceInfo.fromMap(_fakeAndroidDeviceInfo); + + expect(androidDeviceInfo.data, _fakeAndroidDeviceInfo); + }); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/ios_device_info_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/ios_device_info_test.dart new file mode 100755 index 00000000..158a17af --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/ios_device_info_test.dart @@ -0,0 +1,53 @@ +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$IosDeviceInfo fromMap | toMap', () { + late final IosDeviceInfo iosDeviceInfo; + late final Map iosDeviceInfoMap; + + setUpAll(() { + const iosUtsnameMap = { + 'release': 'release', + 'version': 'version', + 'machine': 'machine', + 'sysname': 'sysname', + 'nodename': 'nodename', + }; + iosDeviceInfoMap = { + 'name': 'name', + 'model': 'model', + 'modelName': 'modelName', + 'utsname': iosUtsnameMap, + 'systemName': 'systemName', + 'isPhysicalDevice': true, + 'isiOSAppOnMac': true, + 'systemVersion': 'systemVersion', + 'localizedModel': 'localizedModel', + 'identifierForVendor': 'identifierForVendor', + }; + + iosDeviceInfo = IosDeviceInfo.fromMap(iosDeviceInfoMap); + }); + + test('fromMap should return $IosDeviceInfo with correct values', () { + expect(iosDeviceInfo.name, 'name'); + expect(iosDeviceInfo.model, 'model'); + expect(iosDeviceInfo.modelName, 'modelName'); + expect(iosDeviceInfo.isPhysicalDevice, isTrue); + expect(iosDeviceInfo.isiOSAppOnMac, isTrue); + expect(iosDeviceInfo.systemName, 'systemName'); + expect(iosDeviceInfo.systemVersion, 'systemVersion'); + expect(iosDeviceInfo.localizedModel, 'localizedModel'); + expect(iosDeviceInfo.utsname.release, 'release'); + expect(iosDeviceInfo.utsname.version, 'version'); + expect(iosDeviceInfo.utsname.machine, 'machine'); + expect(iosDeviceInfo.utsname.sysname, 'sysname'); + expect(iosDeviceInfo.utsname.nodename, 'nodename'); + }); + + test('toMap should return map with correct key and map', () { + expect(iosDeviceInfo.data, equals(iosDeviceInfoMap)); + }); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/linux_device_info_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/linux_device_info_test.dart new file mode 100755 index 00000000..761d0202 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/linux_device_info_test.dart @@ -0,0 +1,59 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$LinuxDeviceInfo', () { + test('toMap should return map with correct key and map', () { + final linuxDeviceInfo = LinuxDeviceInfo( + name: 'name', + version: 'version', + id: 'id', + idLike: ['idLike'], + versionCodename: 'versionCodename', + versionId: 'versionId', + prettyName: 'prettyName', + buildId: 'buildId', + variant: 'variant', + variantId: 'variantId', + machineId: 'machineId', + ); + + expect(linuxDeviceInfo.data, { + 'name': 'name', + 'version': 'version', + 'id': 'id', + 'idLike': ['idLike'], + 'versionCodename': 'versionCodename', + 'versionId': 'versionId', + 'prettyName': 'prettyName', + 'buildId': 'buildId', + 'variant': 'variant', + 'variantId': 'variantId', + 'machineId': 'machineId', + }); + }); + + test('toString should return string representation', () { + final linuxDeviceInfo = LinuxDeviceInfo( + name: 'name', + version: 'version', + id: 'id', + idLike: ['idLike'], + versionCodename: 'versionCodename', + versionId: 'versionId', + prettyName: 'prettyName', + buildId: 'buildId', + variant: 'variant', + variantId: 'variantId', + machineId: 'machineId', + ); + + expect( + linuxDeviceInfo.toString(), + 'LinuxDeviceInfo(name: name, version: version, id: id, idLike: [idLike], versionCodename: versionCodename, versionId: versionId, prettyName: prettyName, buildId: buildId, variant: variant, variantId: variantId, machineId: machineId)', + ); + }); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/macos_device_info_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/macos_device_info_test.dart new file mode 100755 index 00000000..ac196762 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/macos_device_info_test.dart @@ -0,0 +1,48 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$MacOsDeviceInfo', () { + group('fromMap | data', () { + const macosDeviceInfoMap = { + 'arch': 'arch', + 'model': 'Mac16,2', + 'modelName': 'iMac (24-inch, 2024)', + 'activeCPUs': 4, + 'memorySize': 16, + 'cpuFrequency': 2, + 'hostName': 'hostName', + 'osRelease': 'osRelease', + 'majorVersion': 10, + 'minorVersion': 9, + 'patchVersion': 3, + 'computerName': 'computerName', + 'kernelVersion': 'kernelVersion', + 'systemGUID': null, + }; + + test('fromMap should return $MacOsDeviceInfo with correct values', () { + final macosDeviceInfo = MacOsDeviceInfo.fromMap(macosDeviceInfoMap); + expect(macosDeviceInfo.arch, 'arch'); + expect(macosDeviceInfo.model, 'Mac16,2'); + expect(macosDeviceInfo.modelName, 'iMac (24-inch, 2024)'); + expect(macosDeviceInfo.activeCPUs, 4); + expect(macosDeviceInfo.memorySize, 16); + expect(macosDeviceInfo.cpuFrequency, 2); + expect(macosDeviceInfo.hostName, 'hostName'); + expect(macosDeviceInfo.osRelease, 'osRelease'); + expect(macosDeviceInfo.majorVersion, 10); + expect(macosDeviceInfo.minorVersion, 9); + expect(macosDeviceInfo.patchVersion, 3); + expect(macosDeviceInfo.systemGUID, isNull); + }); + + test('toMap should return map with correct key and map', () { + final macosDeviceInfo = MacOsDeviceInfo.fromMap(macosDeviceInfoMap); + expect(macosDeviceInfo.data, macosDeviceInfoMap); + }); + }); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/web_browser_info_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/web_browser_info_test.dart new file mode 100755 index 00000000..15b4f497 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/web_browser_info_test.dart @@ -0,0 +1,53 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$WebBrowserInfo', () { + group('fromMap | toMap', () { + const webBrowserInfoMap = { + 'browserName': BrowserName.safari, + 'appCodeName': 'appCodeName', + 'appName': 'appName', + 'appVersion': 'appVersion', + 'deviceMemory': 42.0, + 'language': 'language', + 'languages': ['en', 'es'], + 'platform': 'platform', + 'product': 'product', + 'productSub': 'productSub', + 'userAgent': 'Safari', + 'vendor': 'vendor', + 'vendorSub': 'vendorSub', + 'hardwareConcurrency': 2, + 'maxTouchPoints': 42, + }; + + test('fromMap should return $WebBrowserInfo with correct values', () { + final webBrowserInfo = WebBrowserInfo.fromMap(webBrowserInfoMap); + + expect(webBrowserInfo.browserName, BrowserName.safari); + expect(webBrowserInfo.appCodeName, 'appCodeName'); + expect(webBrowserInfo.appName, 'appName'); + expect(webBrowserInfo.appVersion, 'appVersion'); + expect(webBrowserInfo.deviceMemory, 42); + expect(webBrowserInfo.language, 'language'); + expect(webBrowserInfo.languages, ['en', 'es']); + expect(webBrowserInfo.platform, 'platform'); + expect(webBrowserInfo.product, 'product'); + expect(webBrowserInfo.productSub, 'productSub'); + expect(webBrowserInfo.userAgent, 'Safari'); + expect(webBrowserInfo.vendor, 'vendor'); + expect(webBrowserInfo.vendorSub, 'vendorSub'); + expect(webBrowserInfo.hardwareConcurrency, 2); + expect(webBrowserInfo.maxTouchPoints, 42); + }); + + test('toMap should return map with correct key and map', () { + final webBrowserInfo = WebBrowserInfo.fromMap(webBrowserInfoMap); + expect(webBrowserInfo.data, webBrowserInfoMap); + }); + }); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/windows_device_info_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/windows_device_info_test.dart new file mode 100755 index 00000000..ee452ca8 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/windows_device_info_test.dart @@ -0,0 +1,67 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'dart:typed_data'; +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$WindowsDeviceInfo', () { + test('toMap should return map with correct key and map', () { + final windowsDeviceInfo = WindowsDeviceInfo( + computerName: 'computerName', + numberOfCores: 4, + systemMemoryInMegabytes: 16, + userName: 'userName', + majorVersion: 10, + minorVersion: 0, + buildNumber: 10240, + platformId: 1, + csdVersion: 'csdVersion', + servicePackMajor: 1, + servicePackMinor: 0, + suitMask: 1, + productType: 1, + reserved: 1, + buildLab: '22000.co_release.210604-1628', + buildLabEx: '22000.1.amd64fre.co_release.210604-1628', + digitalProductId: Uint8List.fromList([]), + displayVersion: '21H2', + editionId: 'Pro', + installDate: DateTime(2022, 04, 02), + productId: '00000-00000-0000-AAAAA', + productName: 'Windows 10 Pro', + registeredOwner: 'registeredOwner', + releaseId: 'releaseId', + deviceId: 'deviceId', + ); + + expect(windowsDeviceInfo.data, { + 'computerName': 'computerName', + 'numberOfCores': 4, + 'systemMemoryInMegabytes': 16, + 'userName': 'userName', + 'majorVersion': 10, + 'minorVersion': 0, + 'buildNumber': 10240, + 'platformId': 1, + 'csdVersion': 'csdVersion', + 'servicePackMajor': 1, + 'servicePackMinor': 0, + 'suitMask': 1, + 'productType': 1, + 'reserved': 1, + 'buildLab': '22000.co_release.210604-1628', + 'buildLabEx': '22000.1.amd64fre.co_release.210604-1628', + 'digitalProductId': Uint8List.fromList([]), + 'displayVersion': '21H2', + 'editionId': 'Pro', + 'installDate': DateTime(2022, 04, 02), + 'productId': '00000-00000-0000-AAAAA', + 'productName': 'Windows 10 Pro', + 'registeredOwner': 'registeredOwner', + 'releaseId': 'releaseId', + 'deviceId': 'deviceId', + }); + }); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux deleted file mode 120000 index 86bc8fab..00000000 --- a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/file_selector_linux-0.9.3+2/ \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/AUTHORS b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/AUTHORS new file mode 100755 index 00000000..557dff97 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/CHANGELOG.md b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/CHANGELOG.md new file mode 100755 index 00000000..3bed8134 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/CHANGELOG.md @@ -0,0 +1,67 @@ +## 0.9.3+2 + +* Updates Pigeon to resolve a compilation failure with some versions of glib. + +## 0.9.3+1 + +* Fixes a regression in 0.9.3 with handling of canceled dialogs. + +## 0.9.3 + +* Updates method channel implementation to use Pigeon. +* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. + +## 0.9.2+1 + +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. +* Migrates `styleFrom` usage in examples off of deprecated `primary` and `onPrimary` parameters. + +## 0.9.2 + +* Adds `getSaveLocation` and deprecates `getSavePath`. +* Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. + +## 0.9.1+3 + +* Sets a cmake_policy compatibility version to fix build warnings. + +## 0.9.1+2 + +* Clarifies explanation of endorsement in README. +* Aligns Dart and Flutter SDK constraints. + +## 0.9.1+1 + +* Updates links for the merge of flutter/plugins into flutter/packages. +* Updates example code for `use_build_context_synchronously` lint. +* Updates minimum Flutter version to 3.0. + +## 0.9.1 + +* Adds `getDirectoryPaths` implementation. + +## 0.9.0+1 + +* Changes XTypeGroup initialization from final to const. +* Updates minimum Flutter version to 2.10. + +## 0.9.0 + +* Moves source to flutter/plugins. + +## 0.0.3 + +* Adds Dart implementation for in-package method channel. + +## 0.0.2+1 + +* Updates README + +## 0.0.2 + +* Updates SDK constraint to signal compatibility with null safety. + +## 0.0.1 + +* Initial Linux implementation of `file_selector`. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/LICENSE b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/LICENSE new file mode 100755 index 00000000..c6823b81 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/README.md new file mode 100755 index 00000000..aa065323 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/README.md @@ -0,0 +1,15 @@ +# file\_selector\_linux + +The Linux implementation of [`file_selector`][1]. + +## Usage + +This package is [endorsed][2], which means you can simply use `file_selector` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. + +[1]: https://pub.dev/packages/file_selector +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/README.md new file mode 100755 index 00000000..96b8bb17 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/get_directory_page.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/get_directory_page.dart new file mode 100755 index 00000000..351b403c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/get_directory_page.dart @@ -0,0 +1,82 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select a directory using `getDirectoryPath`, +/// then displays the selected directory in a dialog. +class GetDirectoryPage extends StatelessWidget { + /// Default Constructor + const GetDirectoryPage({super.key}); + + Future _getDirectoryPath(BuildContext context) async { + const String confirmButtonText = 'Choose'; + final String? directoryPath = + await FileSelectorPlatform.instance.getDirectoryPath( + confirmButtonText: confirmButtonText, + ); + if (directoryPath == null) { + // Operation was canceled by the user. + return; + } + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => TextDisplay(directoryPath), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open a text file'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text('Press to ask user to choose a directory'), + onPressed: () => _getDirectoryPath(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Creates a `TextDisplay`. + const TextDisplay(this.directoryPath, {super.key}); + + /// The path selected in the dialog. + final String directoryPath; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text('Selected Directory'), + content: Scrollbar( + child: SingleChildScrollView( + child: Text(directoryPath), + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/get_multiple_directories_page.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/get_multiple_directories_page.dart new file mode 100755 index 00000000..af53822a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/get_multiple_directories_page.dart @@ -0,0 +1,84 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select one or more directories using `getDirectoryPaths`, +/// then displays the selected directories in a dialog. +class GetMultipleDirectoriesPage extends StatelessWidget { + /// Default Constructor + const GetMultipleDirectoriesPage({super.key}); + + Future _getDirectoryPaths(BuildContext context) async { + const String confirmButtonText = 'Choose'; + final List directoryPaths = + await FileSelectorPlatform.instance.getDirectoryPaths( + confirmButtonText: confirmButtonText, + ); + if (directoryPaths.isEmpty) { + // Operation was canceled by the user. + return; + } + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => + TextDisplay(directoryPaths.join('\n')), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Select multiple directories'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text( + 'Press to ask user to choose multiple directories'), + onPressed: () => _getDirectoryPaths(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Creates a `TextDisplay`. + const TextDisplay(this.directoriesPaths, {super.key}); + + /// The path selected in the dialog. + final String directoriesPaths; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text('Selected Directories'), + content: Scrollbar( + child: SingleChildScrollView( + child: Text(directoriesPaths), + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/home_page.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/home_page.dart new file mode 100755 index 00000000..4715f267 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/home_page.dart @@ -0,0 +1,67 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +/// Home Page of the application. +class HomePage extends StatelessWidget { + /// Default Constructor + const HomePage({super.key}); + + @override + Widget build(BuildContext context) { + final ButtonStyle style = ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ); + return Scaffold( + appBar: AppBar( + title: const Text('File Selector Demo Home Page'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: style, + child: const Text('Open a text file'), + onPressed: () => Navigator.pushNamed(context, '/open/text'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Open an image'), + onPressed: () => Navigator.pushNamed(context, '/open/image'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Open multiple images'), + onPressed: () => Navigator.pushNamed(context, '/open/images'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Save a file'), + onPressed: () => Navigator.pushNamed(context, '/save/text'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Open a get directory dialog'), + onPressed: () => Navigator.pushNamed(context, '/directory'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Open a get directories dialog'), + onPressed: () => + Navigator.pushNamed(context, '/multi-directories'), + ), + ], + ), + ), + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/main.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/main.dart new file mode 100755 index 00000000..a88f850f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/main.dart @@ -0,0 +1,45 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +import 'get_directory_page.dart'; +import 'get_multiple_directories_page.dart'; +import 'home_page.dart'; +import 'open_image_page.dart'; +import 'open_multiple_images_page.dart'; +import 'open_text_page.dart'; +import 'save_text_page.dart'; + +void main() { + runApp(const MyApp()); +} + +/// MyApp is the Main Application. +class MyApp extends StatelessWidget { + /// Default Constructor + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'File Selector Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + visualDensity: VisualDensity.adaptivePlatformDensity, + ), + home: const HomePage(), + routes: { + '/open/image': (BuildContext context) => const OpenImagePage(), + '/open/images': (BuildContext context) => + const OpenMultipleImagesPage(), + '/open/text': (BuildContext context) => const OpenTextPage(), + '/save/text': (BuildContext context) => SaveTextPage(), + '/directory': (BuildContext context) => const GetDirectoryPage(), + '/multi-directories': (BuildContext context) => + const GetMultipleDirectoriesPage() + }, + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/open_image_page.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/open_image_page.dart new file mode 100755 index 00000000..e39dee95 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/open_image_page.dart @@ -0,0 +1,92 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select an image file using +/// `openFiles`, then displays the selected images in a gallery dialog. +class OpenImagePage extends StatelessWidget { + /// Default Constructor + const OpenImagePage({super.key}); + + Future _openImageFile(BuildContext context) async { + const XTypeGroup typeGroup = XTypeGroup( + label: 'images', + extensions: ['jpg', 'png'], + ); + final XFile? file = await FileSelectorPlatform.instance + .openFile(acceptedTypeGroups: [typeGroup]); + if (file == null) { + // Operation was canceled by the user. + return; + } + final String fileName = file.name; + final String filePath = file.path; + + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => ImageDisplay(fileName, filePath), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open an image'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text('Press to open an image file(png, jpg)'), + onPressed: () => _openImageFile(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays an image in a dialog. +class ImageDisplay extends StatelessWidget { + /// Default Constructor. + const ImageDisplay(this.fileName, this.filePath, {super.key}); + + /// The name of the selected file. + final String fileName; + + /// The path to the selected file. + final String filePath; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(fileName), + // On web the filePath is a blob url + // while on other platforms it is a system path. + content: kIsWeb ? Image.network(filePath) : Image.file(File(filePath)), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () { + Navigator.pop(context); + }, + ), + ], + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/open_multiple_images_page.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/open_multiple_images_page.dart new file mode 100755 index 00000000..decb1b64 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/open_multiple_images_page.dart @@ -0,0 +1,104 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select multiple image files using +/// `openFiles`, then displays the selected images in a gallery dialog. +class OpenMultipleImagesPage extends StatelessWidget { + /// Default Constructor + const OpenMultipleImagesPage({super.key}); + + Future _openImageFile(BuildContext context) async { + const XTypeGroup jpgsTypeGroup = XTypeGroup( + label: 'JPEGs', + extensions: ['jpg', 'jpeg'], + ); + const XTypeGroup pngTypeGroup = XTypeGroup( + label: 'PNGs', + extensions: ['png'], + ); + final List files = await FileSelectorPlatform.instance + .openFiles(acceptedTypeGroups: [ + jpgsTypeGroup, + pngTypeGroup, + ]); + if (files.isEmpty) { + // Operation was canceled by the user. + return; + } + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => MultipleImagesDisplay(files), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open multiple images'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text('Press to open multiple images (png, jpg)'), + onPressed: () => _openImageFile(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays a text file in a dialog. +class MultipleImagesDisplay extends StatelessWidget { + /// Default Constructor. + const MultipleImagesDisplay(this.files, {super.key}); + + /// The files containing the images. + final List files; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text('Gallery'), + // On web the filePath is a blob url + // while on other platforms it is a system path. + content: Center( + child: Row( + children: [ + ...files.map( + (XFile file) => Flexible( + child: kIsWeb + ? Image.network(file.path) + : Image.file(File(file.path))), + ) + ], + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () { + Navigator.pop(context); + }, + ), + ], + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/open_text_page.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/open_text_page.dart new file mode 100755 index 00000000..6ffbd28c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/open_text_page.dart @@ -0,0 +1,89 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select a text file using `openFile`, then +/// displays its contents in a dialog. +class OpenTextPage extends StatelessWidget { + /// Default Constructor + const OpenTextPage({super.key}); + + Future _openTextFile(BuildContext context) async { + const XTypeGroup typeGroup = XTypeGroup( + label: 'text', + extensions: ['txt', 'json'], + ); + final XFile? file = await FileSelectorPlatform.instance + .openFile(acceptedTypeGroups: [typeGroup]); + if (file == null) { + // Operation was canceled by the user. + return; + } + final String fileName = file.name; + final String fileContent = await file.readAsString(); + + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => TextDisplay(fileName, fileContent), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open a text file'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text('Press to open a text file (json, txt)'), + onPressed: () => _openTextFile(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Default Constructor. + const TextDisplay(this.fileName, this.fileContent, {super.key}); + + /// The name of the selected file. + final String fileName; + + /// The contents of the text file. + final String fileContent; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(fileName), + content: Scrollbar( + child: SingleChildScrollView( + child: Text(fileContent), + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/save_text_page.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/save_text_page.dart new file mode 100755 index 00000000..100da3ab --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/lib/save_text_page.dart @@ -0,0 +1,82 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:typed_data'; +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select a save location using `getSavePath`, +/// then writes text to a file at that location. +class SaveTextPage extends StatelessWidget { + /// Default Constructor + SaveTextPage({super.key}); + + final TextEditingController _nameController = TextEditingController(); + final TextEditingController _contentController = TextEditingController(); + + Future _saveFile() async { + final String fileName = _nameController.text; + final FileSaveLocation? result = + await FileSelectorPlatform.instance.getSaveLocation( + options: SaveDialogOptions(suggestedName: fileName), + ); + // Operation was canceled by the user. + if (result == null) { + return; + } + final String text = _contentController.text; + final Uint8List fileData = Uint8List.fromList(text.codeUnits); + const String fileMimeType = 'text/plain'; + final XFile textFile = + XFile.fromData(fileData, mimeType: fileMimeType, name: fileName); + await textFile.saveTo(result.path); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Save text into a file'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: 300, + child: TextField( + minLines: 1, + maxLines: 12, + controller: _nameController, + decoration: const InputDecoration( + hintText: '(Optional) Suggest File Name', + ), + ), + ), + SizedBox( + width: 300, + child: TextField( + minLines: 1, + maxLines: 12, + controller: _contentController, + decoration: const InputDecoration( + hintText: 'Enter File Contents', + ), + ), + ), + const SizedBox(height: 10), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + onPressed: _saveFile, + child: const Text('Press to save a text file'), + ), + ], + ), + ), + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/CMakeLists.txt new file mode 100755 index 00000000..9d7224cc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/CMakeLists.txt @@ -0,0 +1,111 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "com.example.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Enable the test target. +set(include_file_selector_linux_tests TRUE) +# Provide an alias for the test target using the name expected by repo tooling. +add_custom_target(unit_tests DEPENDS file_selector_linux_test) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..33fd5801 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/flutter/generated_plugins.cmake b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/flutter/generated_plugins.cmake new file mode 100755 index 00000000..2db3c22a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/main.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/main.cc new file mode 100755 index 00000000..1507d028 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/main.cc @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/my_application.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/my_application.cc new file mode 100755 index 00000000..e970be04 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/my_application.cc @@ -0,0 +1,110 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments( + project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, + gchar*** arguments, + int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = + my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/my_application.h b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/my_application.h new file mode 100755 index 00000000..6e9f0c3f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/linux/my_application.h @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/pubspec.yaml new file mode 100755 index 00000000..d29d3dac --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/example/pubspec.yaml @@ -0,0 +1,22 @@ +name: file_selector_linux_example +description: Local testbed for Linux file_selector implementation. +publish_to: 'none' +version: 1.0.0+1 + +environment: + sdk: ^3.3.0 + flutter: ">=3.19.0" + +dependencies: + file_selector_linux: + path: ../ + file_selector_platform_interface: ^2.6.0 + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/lib/file_selector_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/lib/file_selector_linux.dart new file mode 100755 index 00000000..3a05243c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/lib/file_selector_linux.dart @@ -0,0 +1,154 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/foundation.dart' show visibleForTesting; + +import 'src/messages.g.dart'; + +/// An implementation of [FileSelectorPlatform] for Linux. +class FileSelectorLinux extends FileSelectorPlatform { + /// Creates a new plugin implementation instance. + FileSelectorLinux({ + @visibleForTesting FileSelectorApi? api, + }) : _hostApi = api ?? FileSelectorApi(); + + final FileSelectorApi _hostApi; + + /// Registers the Linux implementation. + static void registerWith() { + FileSelectorPlatform.instance = FileSelectorLinux(); + } + + @override + Future openFile({ + List? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) async { + final List paths = await _hostApi.showFileChooser( + PlatformFileChooserActionType.open, + PlatformFileChooserOptions( + allowedFileTypes: + _platformTypeGroupsFromXTypeGroups(acceptedTypeGroups), + currentFolderPath: initialDirectory, + acceptButtonLabel: confirmButtonText, + selectMultiple: false, + )); + return paths.isEmpty ? null : XFile(paths.first); + } + + @override + Future> openFiles({ + List? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) async { + final List paths = await _hostApi.showFileChooser( + PlatformFileChooserActionType.open, + PlatformFileChooserOptions( + allowedFileTypes: + _platformTypeGroupsFromXTypeGroups(acceptedTypeGroups), + currentFolderPath: initialDirectory, + acceptButtonLabel: confirmButtonText, + selectMultiple: true, + )); + return paths.map((String path) => XFile(path)).toList(); + } + + @override + Future getSavePath({ + List? acceptedTypeGroups, + String? initialDirectory, + String? suggestedName, + String? confirmButtonText, + }) async { + final FileSaveLocation? location = await getSaveLocation( + acceptedTypeGroups: acceptedTypeGroups, + options: SaveDialogOptions( + initialDirectory: initialDirectory, + suggestedName: suggestedName, + confirmButtonText: confirmButtonText, + )); + return location?.path; + } + + @override + Future getSaveLocation({ + List? acceptedTypeGroups, + SaveDialogOptions options = const SaveDialogOptions(), + }) async { + // TODO(stuartmorgan): Add the selected type group here and return it. See + // https://github.com/flutter/flutter/issues/107093 + final List paths = await _hostApi.showFileChooser( + PlatformFileChooserActionType.save, + PlatformFileChooserOptions( + allowedFileTypes: + _platformTypeGroupsFromXTypeGroups(acceptedTypeGroups), + currentFolderPath: options.initialDirectory, + currentName: options.suggestedName, + acceptButtonLabel: options.confirmButtonText, + )); + return paths.isEmpty ? null : FileSaveLocation(paths.first); + } + + @override + Future getDirectoryPath({ + String? initialDirectory, + String? confirmButtonText, + }) async { + final List paths = await _hostApi.showFileChooser( + PlatformFileChooserActionType.chooseDirectory, + PlatformFileChooserOptions( + currentFolderPath: initialDirectory, + acceptButtonLabel: confirmButtonText, + selectMultiple: false, + )); + return paths.isEmpty ? null : paths.first; + } + + @override + Future> getDirectoryPaths({ + String? initialDirectory, + String? confirmButtonText, + }) async { + return _hostApi.showFileChooser( + PlatformFileChooserActionType.chooseDirectory, + PlatformFileChooserOptions( + currentFolderPath: initialDirectory, + acceptButtonLabel: confirmButtonText, + selectMultiple: true, + )); + } +} + +List? _platformTypeGroupsFromXTypeGroups( + List? groups) { + return groups?.map(_platformTypeGroupFromXTypeGroup).toList(); +} + +PlatformTypeGroup _platformTypeGroupFromXTypeGroup(XTypeGroup group) { + final String label = group.label ?? ''; + if (group.allowsAny) { + return PlatformTypeGroup( + label: label, + extensions: ['*'], + ); + } + if ((group.extensions?.isEmpty ?? true) && + (group.mimeTypes?.isEmpty ?? true)) { + throw ArgumentError('Provided type group $group does not allow ' + 'all files, but does not set any of the Linux-supported filter ' + 'categories. "extensions" or "mimeTypes" must be non-empty for Linux ' + 'if anything is non-empty.'); + } + return PlatformTypeGroup( + label: label, + // Covert to GtkFileFilter's *. format. + extensions: group.extensions + ?.map((String extension) => '*.$extension') + .toList() ?? + [], + mimeTypes: group.mimeTypes ?? []); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/CMakeLists.txt new file mode 100755 index 00000000..148819dc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 3.10) +set(PROJECT_NAME "file_selector_linux") +project(${PROJECT_NAME} LANGUAGES CXX) + +cmake_policy(VERSION 3.10...3.24) + +set(PLUGIN_NAME "${PROJECT_NAME}_plugin") + +list(APPEND PLUGIN_SOURCES + "file_selector_plugin.cc" + "messages.g.cc" +) + +add_library(${PLUGIN_NAME} SHARED + ${PLUGIN_SOURCES} +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) +target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) + + +# === Tests === + +if(${include_${PROJECT_NAME}_tests}) +if(${CMAKE_VERSION} VERSION_LESS "3.11.0") +message("Unit tests require CMake 3.11.0 or later") +else() +set(TEST_RUNNER "${PROJECT_NAME}_test") +enable_testing() +# TODO(stuartmorgan): Consider using a single shared, pre-checked-in googletest +# instance rather than downloading for each plugin. This approach makes sense +# for a template, but not for a monorepo with many plugins. +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/release-1.11.0.zip +) +# Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Disable install commands for gtest so it doesn't end up in the bundle. +set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE) + +FetchContent_MakeAvailable(googletest) + +# The plugin's exported API is not very useful for unit testing, so build the +# sources directly into the test binary rather than using the shared library. +add_executable(${TEST_RUNNER} + test/file_selector_plugin_test.cc + test/test_main.cc + ${PLUGIN_SOURCES} +) +apply_standard_settings(${TEST_RUNNER}) +target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") +target_link_libraries(${TEST_RUNNER} PRIVATE flutter) +target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK) +target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) + +include(GoogleTest) +gtest_add_tests(TARGET ${TEST_RUNNER}) +# TODO(stuartmorgan): Ensure that all of the necessary steps are running under +# xvfb, and re-enable this. +#gtest_discover_tests(${TEST_RUNNER}) +endif() # CMake version check +endif() # include_${PROJECT_NAME}_tests diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/file_selector_plugin.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/file_selector_plugin.cc new file mode 100755 index 00000000..e8095d58 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/file_selector_plugin.cc @@ -0,0 +1,195 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "include/file_selector_linux/file_selector_plugin.h" + +#include +#include + +#include "file_selector_plugin_private.h" +#include "messages.g.h" + +// Error codes. +const char kBadArgumentsError[] = "Bad Arguments"; +const char kNoScreenError[] = "No Screen"; + +struct _FlFileSelectorPlugin { + GObject parent_instance; + + FlPluginRegistrar* registrar; +}; + +G_DEFINE_TYPE(FlFileSelectorPlugin, fl_file_selector_plugin, G_TYPE_OBJECT) + +// Converts a type group received from Flutter into a GTK file filter. +static GtkFileFilter* type_group_to_filter(FfsPlatformTypeGroup* group) { + g_autoptr(GtkFileFilter) filter = gtk_file_filter_new(); + + const gchar* label = ffs_platform_type_group_get_label(group); + gtk_file_filter_set_name(filter, label); + + FlValue* extensions = ffs_platform_type_group_get_extensions(group); + for (size_t i = 0; i < fl_value_get_length(extensions); i++) { + FlValue* v = fl_value_get_list_value(extensions, i); + const gchar* pattern = fl_value_get_string(v); + gtk_file_filter_add_pattern(filter, pattern); + } + FlValue* mime_types = ffs_platform_type_group_get_mime_types(group); + for (size_t i = 0; i < fl_value_get_length(mime_types); i++) { + FlValue* v = fl_value_get_list_value(mime_types, i); + const gchar* pattern = fl_value_get_string(v); + gtk_file_filter_add_mime_type(filter, pattern); + } + + return GTK_FILE_FILTER(g_object_ref(filter)); +} + +// Creates a GtkFileChooserNative for the given method call details. +static GtkFileChooserNative* create_dialog( + GtkWindow* window, GtkFileChooserAction action, const gchar* title, + const gchar* default_confirm_button_text, + FfsPlatformFileChooserOptions* options) { + const gchar* confirm_button_text = + ffs_platform_file_chooser_options_get_accept_button_label(options); + if (confirm_button_text == nullptr) { + confirm_button_text = default_confirm_button_text; + } + + g_autoptr(GtkFileChooserNative) dialog = + GTK_FILE_CHOOSER_NATIVE(gtk_file_chooser_native_new( + title, window, action, confirm_button_text, "_Cancel")); + + const gboolean* select_multiple = + ffs_platform_file_chooser_options_get_select_multiple(options); + if (select_multiple != nullptr) { + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), + *select_multiple); + } + + const gchar* current_folder = + ffs_platform_file_chooser_options_get_current_folder_path(options); + if (current_folder != nullptr) { + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), + current_folder); + } + + const gchar* current_name = + ffs_platform_file_chooser_options_get_current_name(options); + if (current_name != nullptr) { + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), current_name); + } + + FlValue* type_groups = + ffs_platform_file_chooser_options_get_allowed_file_types(options); + if (type_groups != nullptr) { + for (size_t i = 0; i < fl_value_get_length(type_groups); i++) { + FlValue* type_group = fl_value_get_list_value(type_groups, i); + GtkFileFilter* filter = type_group_to_filter(FFS_PLATFORM_TYPE_GROUP( + fl_value_get_custom_value_object(type_group))); + if (filter == nullptr) { + return nullptr; + } + gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter); + } + } + + return GTK_FILE_CHOOSER_NATIVE(g_object_ref(dialog)); +} + +GtkFileChooserNative* create_dialog_of_type( + GtkWindow* window, FfsPlatformFileChooserActionType type, + FfsPlatformFileChooserOptions* options) { + switch (type) { + case FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_OPEN: + return create_dialog(window, GTK_FILE_CHOOSER_ACTION_OPEN, "Open File", + "_Open", options); + case FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_CHOOSE_DIRECTORY: + return create_dialog(window, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + "Choose Directory", "_Open", options); + case FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_SAVE: + return create_dialog(window, GTK_FILE_CHOOSER_ACTION_SAVE, "Save File", + "_Save", options); + } + return nullptr; +} + +// Shows the requested dialog type. +static FfsFileSelectorApiShowFileChooserResponse* handle_show_file_chooser( + FfsPlatformFileChooserActionType type, + FfsPlatformFileChooserOptions* options, gpointer user_data) { + FlFileSelectorPlugin* self = FL_FILE_SELECTOR_PLUGIN(user_data); + + FlView* view = fl_plugin_registrar_get_view(self->registrar); + if (view == nullptr) { + return ffs_file_selector_api_show_file_chooser_response_new_error( + kNoScreenError, nullptr, nullptr); + } + GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))); + + g_autoptr(GtkFileChooserNative) dialog = + create_dialog_of_type(window, type, options); + + if (dialog == nullptr) { + return ffs_file_selector_api_show_file_chooser_response_new_error( + kBadArgumentsError, "Unable to create dialog from arguments", nullptr); + } + return show_file_chooser(GTK_FILE_CHOOSER_NATIVE(dialog), + gtk_native_dialog_run); +} + +FfsFileSelectorApiShowFileChooserResponse* show_file_chooser( + GtkFileChooserNative* dialog, gint (*run_dialog)(GtkNativeDialog*)) { + gint response = run_dialog(GTK_NATIVE_DIALOG(dialog)); + g_autoptr(FlValue) result = fl_value_new_list(); + if (response == GTK_RESPONSE_ACCEPT) { + g_autoptr(GSList) filenames = + gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + for (GSList* link = filenames; link != nullptr; link = link->next) { + g_autofree gchar* filename = static_cast(link->data); + fl_value_append_take(result, fl_value_new_string(filename)); + } + } + + return ffs_file_selector_api_show_file_chooser_response_new(result); +} + +static void fl_file_selector_plugin_dispose(GObject* object) { + FlFileSelectorPlugin* self = FL_FILE_SELECTOR_PLUGIN(object); + + ffs_file_selector_api_clear_method_handlers( + fl_plugin_registrar_get_messenger(self->registrar), nullptr); + g_clear_object(&self->registrar); + + G_OBJECT_CLASS(fl_file_selector_plugin_parent_class)->dispose(object); +} + +static void fl_file_selector_plugin_class_init( + FlFileSelectorPluginClass* klass) { + G_OBJECT_CLASS(klass)->dispose = fl_file_selector_plugin_dispose; +} + +static void fl_file_selector_plugin_init(FlFileSelectorPlugin* self) {} + +FlFileSelectorPlugin* fl_file_selector_plugin_new( + FlPluginRegistrar* registrar) { + FlFileSelectorPlugin* self = FL_FILE_SELECTOR_PLUGIN( + g_object_new(fl_file_selector_plugin_get_type(), nullptr)); + + self->registrar = FL_PLUGIN_REGISTRAR(g_object_ref(registrar)); + + static FfsFileSelectorApiVTable api_vtable = { + .show_file_chooser = handle_show_file_chooser, + }; + ffs_file_selector_api_set_method_handlers( + fl_plugin_registrar_get_messenger(registrar), nullptr, &api_vtable, + g_object_ref(self), g_object_unref); + + return self; +} + +void file_selector_plugin_register_with_registrar( + FlPluginRegistrar* registrar) { + FlFileSelectorPlugin* plugin = fl_file_selector_plugin_new(registrar); + g_object_unref(plugin); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/file_selector_plugin_private.h b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/file_selector_plugin_private.h new file mode 100755 index 00000000..3a8a9b10 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/file_selector_plugin_private.h @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include + +#include "include/file_selector_linux/file_selector_plugin.h" +#include "messages.g.h" + +// Creates a GtkFileChooserNative for the given method call. +// +// TODO(stuartmorgan): Make this private/static once the tests are restructured +// as descibed in the file_selector_plugin_test.cc TODOs, and then test through +// the Pigeon API handler instead (making that non-static). This only exists to +// move as much logic as possible behind an entry point currently callable by +// unit tests. +GtkFileChooserNative* create_dialog_of_type( + GtkWindow* window, FfsPlatformFileChooserActionType type, + FfsPlatformFileChooserOptions* options); + +// TODO(stuartmorgan): Fold this into handle_show_file_chooser as part of the +// above TODO. This only exists to allow testing response generation without +// mocking out all of the GTK calls. +FfsFileSelectorApiShowFileChooserResponse* show_file_chooser( + GtkFileChooserNative* dialog, gint (*run_dialog)(GtkNativeDialog*)); diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/include/file_selector_linux/file_selector_plugin.h b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/include/file_selector_linux/file_selector_plugin.h new file mode 100755 index 00000000..98e90e5d --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/include/file_selector_linux/file_selector_plugin.h @@ -0,0 +1,31 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PLUGINS_FILE_SELECTOR_LINUX_FILE_SELECTOR_PLUGIN_H_ +#define PLUGINS_FILE_SELECTOR_LINUX_FILE_SELECTOR_PLUGIN_H_ + +// A plugin to show native save/open file choosers. + +#include + +G_BEGIN_DECLS + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define FLUTTER_PLUGIN_EXPORT +#endif + +G_DECLARE_FINAL_TYPE(FlFileSelectorPlugin, fl_file_selector_plugin, FL, + FILE_SELECTOR_PLUGIN, GObject) + +FLUTTER_PLUGIN_EXPORT FlFileSelectorPlugin* fl_file_selector_plugin_new( + FlPluginRegistrar* registrar); + +FLUTTER_PLUGIN_EXPORT void file_selector_plugin_register_with_registrar( + FlPluginRegistrar* registrar); + +G_END_DECLS + +#endif // PLUGINS_FILE_SELECTOR_LINUX_FILE_SELECTOR_PLUGIN_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/messages.g.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/messages.g.cc new file mode 100755 index 00000000..6c6bfc77 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/messages.g.cc @@ -0,0 +1,539 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v22.6.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#include "messages.g.h" + +struct _FfsPlatformTypeGroup { + GObject parent_instance; + + gchar* label; + FlValue* extensions; + FlValue* mime_types; +}; + +G_DEFINE_TYPE(FfsPlatformTypeGroup, ffs_platform_type_group, G_TYPE_OBJECT) + +static void ffs_platform_type_group_dispose(GObject* object) { + FfsPlatformTypeGroup* self = FFS_PLATFORM_TYPE_GROUP(object); + g_clear_pointer(&self->label, g_free); + g_clear_pointer(&self->extensions, fl_value_unref); + g_clear_pointer(&self->mime_types, fl_value_unref); + G_OBJECT_CLASS(ffs_platform_type_group_parent_class)->dispose(object); +} + +static void ffs_platform_type_group_init(FfsPlatformTypeGroup* self) {} + +static void ffs_platform_type_group_class_init( + FfsPlatformTypeGroupClass* klass) { + G_OBJECT_CLASS(klass)->dispose = ffs_platform_type_group_dispose; +} + +FfsPlatformTypeGroup* ffs_platform_type_group_new(const gchar* label, + FlValue* extensions, + FlValue* mime_types) { + FfsPlatformTypeGroup* self = FFS_PLATFORM_TYPE_GROUP( + g_object_new(ffs_platform_type_group_get_type(), nullptr)); + self->label = g_strdup(label); + self->extensions = fl_value_ref(extensions); + self->mime_types = fl_value_ref(mime_types); + return self; +} + +const gchar* ffs_platform_type_group_get_label(FfsPlatformTypeGroup* self) { + g_return_val_if_fail(FFS_IS_PLATFORM_TYPE_GROUP(self), nullptr); + return self->label; +} + +FlValue* ffs_platform_type_group_get_extensions(FfsPlatformTypeGroup* self) { + g_return_val_if_fail(FFS_IS_PLATFORM_TYPE_GROUP(self), nullptr); + return self->extensions; +} + +FlValue* ffs_platform_type_group_get_mime_types(FfsPlatformTypeGroup* self) { + g_return_val_if_fail(FFS_IS_PLATFORM_TYPE_GROUP(self), nullptr); + return self->mime_types; +} + +static FlValue* ffs_platform_type_group_to_list(FfsPlatformTypeGroup* self) { + FlValue* values = fl_value_new_list(); + fl_value_append_take(values, fl_value_new_string(self->label)); + fl_value_append_take(values, fl_value_ref(self->extensions)); + fl_value_append_take(values, fl_value_ref(self->mime_types)); + return values; +} + +static FfsPlatformTypeGroup* ffs_platform_type_group_new_from_list( + FlValue* values) { + FlValue* value0 = fl_value_get_list_value(values, 0); + const gchar* label = fl_value_get_string(value0); + FlValue* value1 = fl_value_get_list_value(values, 1); + FlValue* extensions = value1; + FlValue* value2 = fl_value_get_list_value(values, 2); + FlValue* mime_types = value2; + return ffs_platform_type_group_new(label, extensions, mime_types); +} + +struct _FfsPlatformFileChooserOptions { + GObject parent_instance; + + FlValue* allowed_file_types; + gchar* current_folder_path; + gchar* current_name; + gchar* accept_button_label; + gboolean* select_multiple; +}; + +G_DEFINE_TYPE(FfsPlatformFileChooserOptions, ffs_platform_file_chooser_options, + G_TYPE_OBJECT) + +static void ffs_platform_file_chooser_options_dispose(GObject* object) { + FfsPlatformFileChooserOptions* self = + FFS_PLATFORM_FILE_CHOOSER_OPTIONS(object); + g_clear_pointer(&self->allowed_file_types, fl_value_unref); + g_clear_pointer(&self->current_folder_path, g_free); + g_clear_pointer(&self->current_name, g_free); + g_clear_pointer(&self->accept_button_label, g_free); + g_clear_pointer(&self->select_multiple, g_free); + G_OBJECT_CLASS(ffs_platform_file_chooser_options_parent_class) + ->dispose(object); +} + +static void ffs_platform_file_chooser_options_init( + FfsPlatformFileChooserOptions* self) {} + +static void ffs_platform_file_chooser_options_class_init( + FfsPlatformFileChooserOptionsClass* klass) { + G_OBJECT_CLASS(klass)->dispose = ffs_platform_file_chooser_options_dispose; +} + +FfsPlatformFileChooserOptions* ffs_platform_file_chooser_options_new( + FlValue* allowed_file_types, const gchar* current_folder_path, + const gchar* current_name, const gchar* accept_button_label, + gboolean* select_multiple) { + FfsPlatformFileChooserOptions* self = FFS_PLATFORM_FILE_CHOOSER_OPTIONS( + g_object_new(ffs_platform_file_chooser_options_get_type(), nullptr)); + if (allowed_file_types != nullptr) { + self->allowed_file_types = fl_value_ref(allowed_file_types); + } else { + self->allowed_file_types = nullptr; + } + if (current_folder_path != nullptr) { + self->current_folder_path = g_strdup(current_folder_path); + } else { + self->current_folder_path = nullptr; + } + if (current_name != nullptr) { + self->current_name = g_strdup(current_name); + } else { + self->current_name = nullptr; + } + if (accept_button_label != nullptr) { + self->accept_button_label = g_strdup(accept_button_label); + } else { + self->accept_button_label = nullptr; + } + if (select_multiple != nullptr) { + self->select_multiple = static_cast(malloc(sizeof(gboolean))); + *self->select_multiple = *select_multiple; + } else { + self->select_multiple = nullptr; + } + return self; +} + +FlValue* ffs_platform_file_chooser_options_get_allowed_file_types( + FfsPlatformFileChooserOptions* self) { + g_return_val_if_fail(FFS_IS_PLATFORM_FILE_CHOOSER_OPTIONS(self), nullptr); + return self->allowed_file_types; +} + +const gchar* ffs_platform_file_chooser_options_get_current_folder_path( + FfsPlatformFileChooserOptions* self) { + g_return_val_if_fail(FFS_IS_PLATFORM_FILE_CHOOSER_OPTIONS(self), nullptr); + return self->current_folder_path; +} + +const gchar* ffs_platform_file_chooser_options_get_current_name( + FfsPlatformFileChooserOptions* self) { + g_return_val_if_fail(FFS_IS_PLATFORM_FILE_CHOOSER_OPTIONS(self), nullptr); + return self->current_name; +} + +const gchar* ffs_platform_file_chooser_options_get_accept_button_label( + FfsPlatformFileChooserOptions* self) { + g_return_val_if_fail(FFS_IS_PLATFORM_FILE_CHOOSER_OPTIONS(self), nullptr); + return self->accept_button_label; +} + +gboolean* ffs_platform_file_chooser_options_get_select_multiple( + FfsPlatformFileChooserOptions* self) { + g_return_val_if_fail(FFS_IS_PLATFORM_FILE_CHOOSER_OPTIONS(self), nullptr); + return self->select_multiple; +} + +static FlValue* ffs_platform_file_chooser_options_to_list( + FfsPlatformFileChooserOptions* self) { + FlValue* values = fl_value_new_list(); + fl_value_append_take(values, self->allowed_file_types != nullptr + ? fl_value_ref(self->allowed_file_types) + : fl_value_new_null()); + fl_value_append_take(values, + self->current_folder_path != nullptr + ? fl_value_new_string(self->current_folder_path) + : fl_value_new_null()); + fl_value_append_take(values, self->current_name != nullptr + ? fl_value_new_string(self->current_name) + : fl_value_new_null()); + fl_value_append_take(values, + self->accept_button_label != nullptr + ? fl_value_new_string(self->accept_button_label) + : fl_value_new_null()); + fl_value_append_take(values, self->select_multiple != nullptr + ? fl_value_new_bool(*self->select_multiple) + : fl_value_new_null()); + return values; +} + +static FfsPlatformFileChooserOptions* +ffs_platform_file_chooser_options_new_from_list(FlValue* values) { + FlValue* value0 = fl_value_get_list_value(values, 0); + FlValue* allowed_file_types = nullptr; + if (fl_value_get_type(value0) != FL_VALUE_TYPE_NULL) { + allowed_file_types = value0; + } + FlValue* value1 = fl_value_get_list_value(values, 1); + const gchar* current_folder_path = nullptr; + if (fl_value_get_type(value1) != FL_VALUE_TYPE_NULL) { + current_folder_path = fl_value_get_string(value1); + } + FlValue* value2 = fl_value_get_list_value(values, 2); + const gchar* current_name = nullptr; + if (fl_value_get_type(value2) != FL_VALUE_TYPE_NULL) { + current_name = fl_value_get_string(value2); + } + FlValue* value3 = fl_value_get_list_value(values, 3); + const gchar* accept_button_label = nullptr; + if (fl_value_get_type(value3) != FL_VALUE_TYPE_NULL) { + accept_button_label = fl_value_get_string(value3); + } + FlValue* value4 = fl_value_get_list_value(values, 4); + gboolean* select_multiple = nullptr; + gboolean select_multiple_value; + if (fl_value_get_type(value4) != FL_VALUE_TYPE_NULL) { + select_multiple_value = fl_value_get_bool(value4); + select_multiple = &select_multiple_value; + } + return ffs_platform_file_chooser_options_new( + allowed_file_types, current_folder_path, current_name, + accept_button_label, select_multiple); +} + +struct _FfsMessageCodec { + FlStandardMessageCodec parent_instance; +}; + +G_DEFINE_TYPE(FfsMessageCodec, ffs_message_codec, + fl_standard_message_codec_get_type()) + +static gboolean ffs_message_codec_write_ffs_platform_file_chooser_action_type( + FlStandardMessageCodec* codec, GByteArray* buffer, FlValue* value, + GError** error) { + uint8_t type = 129; + g_byte_array_append(buffer, &type, sizeof(uint8_t)); + return fl_standard_message_codec_write_value(codec, buffer, value, error); +} + +static gboolean ffs_message_codec_write_ffs_platform_type_group( + FlStandardMessageCodec* codec, GByteArray* buffer, + FfsPlatformTypeGroup* value, GError** error) { + uint8_t type = 130; + g_byte_array_append(buffer, &type, sizeof(uint8_t)); + g_autoptr(FlValue) values = ffs_platform_type_group_to_list(value); + return fl_standard_message_codec_write_value(codec, buffer, values, error); +} + +static gboolean ffs_message_codec_write_ffs_platform_file_chooser_options( + FlStandardMessageCodec* codec, GByteArray* buffer, + FfsPlatformFileChooserOptions* value, GError** error) { + uint8_t type = 131; + g_byte_array_append(buffer, &type, sizeof(uint8_t)); + g_autoptr(FlValue) values = ffs_platform_file_chooser_options_to_list(value); + return fl_standard_message_codec_write_value(codec, buffer, values, error); +} + +static gboolean ffs_message_codec_write_value(FlStandardMessageCodec* codec, + GByteArray* buffer, + FlValue* value, GError** error) { + if (fl_value_get_type(value) == FL_VALUE_TYPE_CUSTOM) { + switch (fl_value_get_custom_type(value)) { + case 129: + return ffs_message_codec_write_ffs_platform_file_chooser_action_type( + codec, buffer, + reinterpret_cast( + const_cast(fl_value_get_custom_value(value))), + error); + case 130: + return ffs_message_codec_write_ffs_platform_type_group( + codec, buffer, + FFS_PLATFORM_TYPE_GROUP(fl_value_get_custom_value_object(value)), + error); + case 131: + return ffs_message_codec_write_ffs_platform_file_chooser_options( + codec, buffer, + FFS_PLATFORM_FILE_CHOOSER_OPTIONS( + fl_value_get_custom_value_object(value)), + error); + } + } + + return FL_STANDARD_MESSAGE_CODEC_CLASS(ffs_message_codec_parent_class) + ->write_value(codec, buffer, value, error); +} + +static FlValue* ffs_message_codec_read_ffs_platform_file_chooser_action_type( + FlStandardMessageCodec* codec, GBytes* buffer, size_t* offset, + GError** error) { + return fl_value_new_custom( + 129, fl_standard_message_codec_read_value(codec, buffer, offset, error), + (GDestroyNotify)fl_value_unref); +} + +static FlValue* ffs_message_codec_read_ffs_platform_type_group( + FlStandardMessageCodec* codec, GBytes* buffer, size_t* offset, + GError** error) { + g_autoptr(FlValue) values = + fl_standard_message_codec_read_value(codec, buffer, offset, error); + if (values == nullptr) { + return nullptr; + } + + g_autoptr(FfsPlatformTypeGroup) value = + ffs_platform_type_group_new_from_list(values); + if (value == nullptr) { + g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED, + "Invalid data received for MessageData"); + return nullptr; + } + + return fl_value_new_custom_object(130, G_OBJECT(value)); +} + +static FlValue* ffs_message_codec_read_ffs_platform_file_chooser_options( + FlStandardMessageCodec* codec, GBytes* buffer, size_t* offset, + GError** error) { + g_autoptr(FlValue) values = + fl_standard_message_codec_read_value(codec, buffer, offset, error); + if (values == nullptr) { + return nullptr; + } + + g_autoptr(FfsPlatformFileChooserOptions) value = + ffs_platform_file_chooser_options_new_from_list(values); + if (value == nullptr) { + g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED, + "Invalid data received for MessageData"); + return nullptr; + } + + return fl_value_new_custom_object(131, G_OBJECT(value)); +} + +static FlValue* ffs_message_codec_read_value_of_type( + FlStandardMessageCodec* codec, GBytes* buffer, size_t* offset, int type, + GError** error) { + switch (type) { + case 129: + return ffs_message_codec_read_ffs_platform_file_chooser_action_type( + codec, buffer, offset, error); + case 130: + return ffs_message_codec_read_ffs_platform_type_group(codec, buffer, + offset, error); + case 131: + return ffs_message_codec_read_ffs_platform_file_chooser_options( + codec, buffer, offset, error); + default: + return FL_STANDARD_MESSAGE_CODEC_CLASS(ffs_message_codec_parent_class) + ->read_value_of_type(codec, buffer, offset, type, error); + } +} + +static void ffs_message_codec_init(FfsMessageCodec* self) {} + +static void ffs_message_codec_class_init(FfsMessageCodecClass* klass) { + FL_STANDARD_MESSAGE_CODEC_CLASS(klass)->write_value = + ffs_message_codec_write_value; + FL_STANDARD_MESSAGE_CODEC_CLASS(klass)->read_value_of_type = + ffs_message_codec_read_value_of_type; +} + +static FfsMessageCodec* ffs_message_codec_new() { + FfsMessageCodec* self = + FFS_MESSAGE_CODEC(g_object_new(ffs_message_codec_get_type(), nullptr)); + return self; +} + +struct _FfsFileSelectorApiShowFileChooserResponse { + GObject parent_instance; + + FlValue* value; +}; + +G_DEFINE_TYPE(FfsFileSelectorApiShowFileChooserResponse, + ffs_file_selector_api_show_file_chooser_response, G_TYPE_OBJECT) + +static void ffs_file_selector_api_show_file_chooser_response_dispose( + GObject* object) { + FfsFileSelectorApiShowFileChooserResponse* self = + FFS_FILE_SELECTOR_API_SHOW_FILE_CHOOSER_RESPONSE(object); + g_clear_pointer(&self->value, fl_value_unref); + G_OBJECT_CLASS(ffs_file_selector_api_show_file_chooser_response_parent_class) + ->dispose(object); +} + +static void ffs_file_selector_api_show_file_chooser_response_init( + FfsFileSelectorApiShowFileChooserResponse* self) {} + +static void ffs_file_selector_api_show_file_chooser_response_class_init( + FfsFileSelectorApiShowFileChooserResponseClass* klass) { + G_OBJECT_CLASS(klass)->dispose = + ffs_file_selector_api_show_file_chooser_response_dispose; +} + +FfsFileSelectorApiShowFileChooserResponse* +ffs_file_selector_api_show_file_chooser_response_new(FlValue* return_value) { + FfsFileSelectorApiShowFileChooserResponse* self = + FFS_FILE_SELECTOR_API_SHOW_FILE_CHOOSER_RESPONSE(g_object_new( + ffs_file_selector_api_show_file_chooser_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_ref(return_value)); + return self; +} + +FfsFileSelectorApiShowFileChooserResponse* +ffs_file_selector_api_show_file_chooser_response_new_error(const gchar* code, + const gchar* message, + FlValue* details) { + FfsFileSelectorApiShowFileChooserResponse* self = + FFS_FILE_SELECTOR_API_SHOW_FILE_CHOOSER_RESPONSE(g_object_new( + ffs_file_selector_api_show_file_chooser_response_get_type(), + nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_string(code)); + fl_value_append_take(self->value, + fl_value_new_string(message != nullptr ? message : "")); + fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details) + : fl_value_new_null()); + return self; +} + +struct _FfsFileSelectorApi { + GObject parent_instance; + + const FfsFileSelectorApiVTable* vtable; + gpointer user_data; + GDestroyNotify user_data_free_func; +}; + +G_DEFINE_TYPE(FfsFileSelectorApi, ffs_file_selector_api, G_TYPE_OBJECT) + +static void ffs_file_selector_api_dispose(GObject* object) { + FfsFileSelectorApi* self = FFS_FILE_SELECTOR_API(object); + if (self->user_data != nullptr) { + self->user_data_free_func(self->user_data); + } + self->user_data = nullptr; + G_OBJECT_CLASS(ffs_file_selector_api_parent_class)->dispose(object); +} + +static void ffs_file_selector_api_init(FfsFileSelectorApi* self) {} + +static void ffs_file_selector_api_class_init(FfsFileSelectorApiClass* klass) { + G_OBJECT_CLASS(klass)->dispose = ffs_file_selector_api_dispose; +} + +static FfsFileSelectorApi* ffs_file_selector_api_new( + const FfsFileSelectorApiVTable* vtable, gpointer user_data, + GDestroyNotify user_data_free_func) { + FfsFileSelectorApi* self = FFS_FILE_SELECTOR_API( + g_object_new(ffs_file_selector_api_get_type(), nullptr)); + self->vtable = vtable; + self->user_data = user_data; + self->user_data_free_func = user_data_free_func; + return self; +} + +static void ffs_file_selector_api_show_file_chooser_cb( + FlBasicMessageChannel* channel, FlValue* message_, + FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { + FfsFileSelectorApi* self = FFS_FILE_SELECTOR_API(user_data); + + if (self->vtable == nullptr || self->vtable->show_file_chooser == nullptr) { + return; + } + + FlValue* value0 = fl_value_get_list_value(message_, 0); + FfsPlatformFileChooserActionType type = + static_cast( + fl_value_get_int(reinterpret_cast( + const_cast(fl_value_get_custom_value(value0))))); + FlValue* value1 = fl_value_get_list_value(message_, 1); + FfsPlatformFileChooserOptions* options = FFS_PLATFORM_FILE_CHOOSER_OPTIONS( + fl_value_get_custom_value_object(value1)); + g_autoptr(FfsFileSelectorApiShowFileChooserResponse) response = + self->vtable->show_file_chooser(type, options, self->user_data); + if (response == nullptr) { + g_warning("No response returned to %s.%s", "FileSelectorApi", + "showFileChooser"); + return; + } + + g_autoptr(GError) error = NULL; + if (!fl_basic_message_channel_respond(channel, response_handle, + response->value, &error)) { + g_warning("Failed to send response to %s.%s: %s", "FileSelectorApi", + "showFileChooser", error->message); + } +} + +void ffs_file_selector_api_set_method_handlers( + FlBinaryMessenger* messenger, const gchar* suffix, + const FfsFileSelectorApiVTable* vtable, gpointer user_data, + GDestroyNotify user_data_free_func) { + g_autofree gchar* dot_suffix = + suffix != nullptr ? g_strdup_printf(".%s", suffix) : g_strdup(""); + g_autoptr(FfsFileSelectorApi) api_data = + ffs_file_selector_api_new(vtable, user_data, user_data_free_func); + + g_autoptr(FfsMessageCodec) codec = ffs_message_codec_new(); + g_autofree gchar* show_file_chooser_channel_name = g_strdup_printf( + "dev.flutter.pigeon.file_selector_linux.FileSelectorApi.showFileChooser%" + "s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) show_file_chooser_channel = + fl_basic_message_channel_new(messenger, show_file_chooser_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler( + show_file_chooser_channel, ffs_file_selector_api_show_file_chooser_cb, + g_object_ref(api_data), g_object_unref); +} + +void ffs_file_selector_api_clear_method_handlers(FlBinaryMessenger* messenger, + const gchar* suffix) { + g_autofree gchar* dot_suffix = + suffix != nullptr ? g_strdup_printf(".%s", suffix) : g_strdup(""); + + g_autoptr(FfsMessageCodec) codec = ffs_message_codec_new(); + g_autofree gchar* show_file_chooser_channel_name = g_strdup_printf( + "dev.flutter.pigeon.file_selector_linux.FileSelectorApi.showFileChooser%" + "s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) show_file_chooser_channel = + fl_basic_message_channel_new(messenger, show_file_chooser_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler(show_file_chooser_channel, + nullptr, nullptr, nullptr); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/messages.g.h b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/messages.g.h new file mode 100755 index 00000000..50810d92 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/messages.g.h @@ -0,0 +1,244 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v22.6.2), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#ifndef PIGEON_MESSAGES_G_H_ +#define PIGEON_MESSAGES_G_H_ + +#include + +G_BEGIN_DECLS + +/** + * FfsPlatformFileChooserActionType: + * FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_OPEN: + * FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_CHOOSE_DIRECTORY: + * FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_SAVE: + * + * A Pigeon representation of the GTK_FILE_CHOOSER_ACTION_* options. + */ +typedef enum { + FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_OPEN = 0, + FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_CHOOSE_DIRECTORY = 1, + FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_SAVE = 2 +} FfsPlatformFileChooserActionType; + +/** + * FfsPlatformTypeGroup: + * + * A Pigeon representation of the Linux portion of an `XTypeGroup`. + */ + +G_DECLARE_FINAL_TYPE(FfsPlatformTypeGroup, ffs_platform_type_group, FFS, + PLATFORM_TYPE_GROUP, GObject) + +/** + * ffs_platform_type_group_new: + * label: field in this object. + * extensions: field in this object. + * mime_types: field in this object. + * + * Creates a new #PlatformTypeGroup object. + * + * Returns: a new #FfsPlatformTypeGroup + */ +FfsPlatformTypeGroup* ffs_platform_type_group_new(const gchar* label, + FlValue* extensions, + FlValue* mime_types); + +/** + * ffs_platform_type_group_get_label + * @object: a #FfsPlatformTypeGroup. + * + * Gets the value of the label field of @object. + * + * Returns: the field value. + */ +const gchar* ffs_platform_type_group_get_label(FfsPlatformTypeGroup* object); + +/** + * ffs_platform_type_group_get_extensions + * @object: a #FfsPlatformTypeGroup. + * + * Gets the value of the extensions field of @object. + * + * Returns: the field value. + */ +FlValue* ffs_platform_type_group_get_extensions(FfsPlatformTypeGroup* object); + +/** + * ffs_platform_type_group_get_mime_types + * @object: a #FfsPlatformTypeGroup. + * + * Gets the value of the mimeTypes field of @object. + * + * Returns: the field value. + */ +FlValue* ffs_platform_type_group_get_mime_types(FfsPlatformTypeGroup* object); + +/** + * FfsPlatformFileChooserOptions: + * + * Options for GKT file chooser. + * + * These correspond to gtk_file_chooser_set_* options. + */ + +G_DECLARE_FINAL_TYPE(FfsPlatformFileChooserOptions, + ffs_platform_file_chooser_options, FFS, + PLATFORM_FILE_CHOOSER_OPTIONS, GObject) + +/** + * ffs_platform_file_chooser_options_new: + * allowed_file_types: field in this object. + * current_folder_path: field in this object. + * current_name: field in this object. + * accept_button_label: field in this object. + * select_multiple: field in this object. + * + * Creates a new #PlatformFileChooserOptions object. + * + * Returns: a new #FfsPlatformFileChooserOptions + */ +FfsPlatformFileChooserOptions* ffs_platform_file_chooser_options_new( + FlValue* allowed_file_types, const gchar* current_folder_path, + const gchar* current_name, const gchar* accept_button_label, + gboolean* select_multiple); + +/** + * ffs_platform_file_chooser_options_get_allowed_file_types + * @object: a #FfsPlatformFileChooserOptions. + * + * Gets the value of the allowedFileTypes field of @object. + * + * Returns: the field value. + */ +FlValue* ffs_platform_file_chooser_options_get_allowed_file_types( + FfsPlatformFileChooserOptions* object); + +/** + * ffs_platform_file_chooser_options_get_current_folder_path + * @object: a #FfsPlatformFileChooserOptions. + * + * Gets the value of the currentFolderPath field of @object. + * + * Returns: the field value. + */ +const gchar* ffs_platform_file_chooser_options_get_current_folder_path( + FfsPlatformFileChooserOptions* object); + +/** + * ffs_platform_file_chooser_options_get_current_name + * @object: a #FfsPlatformFileChooserOptions. + * + * Gets the value of the currentName field of @object. + * + * Returns: the field value. + */ +const gchar* ffs_platform_file_chooser_options_get_current_name( + FfsPlatformFileChooserOptions* object); + +/** + * ffs_platform_file_chooser_options_get_accept_button_label + * @object: a #FfsPlatformFileChooserOptions. + * + * Gets the value of the acceptButtonLabel field of @object. + * + * Returns: the field value. + */ +const gchar* ffs_platform_file_chooser_options_get_accept_button_label( + FfsPlatformFileChooserOptions* object); + +/** + * ffs_platform_file_chooser_options_get_select_multiple + * @object: a #FfsPlatformFileChooserOptions. + * + * Whether to allow multiple file selection. + * + * Nullable because it does not apply to the "save" action. + * + * Returns: the field value. + */ +gboolean* ffs_platform_file_chooser_options_get_select_multiple( + FfsPlatformFileChooserOptions* object); + +G_DECLARE_FINAL_TYPE(FfsMessageCodec, ffs_message_codec, FFS, MESSAGE_CODEC, + FlStandardMessageCodec) + +G_DECLARE_FINAL_TYPE(FfsFileSelectorApi, ffs_file_selector_api, FFS, + FILE_SELECTOR_API, GObject) + +G_DECLARE_FINAL_TYPE(FfsFileSelectorApiShowFileChooserResponse, + ffs_file_selector_api_show_file_chooser_response, FFS, + FILE_SELECTOR_API_SHOW_FILE_CHOOSER_RESPONSE, GObject) + +/** + * ffs_file_selector_api_show_file_chooser_response_new: + * + * Creates a new response to FileSelectorApi.showFileChooser. + * + * Returns: a new #FfsFileSelectorApiShowFileChooserResponse + */ +FfsFileSelectorApiShowFileChooserResponse* +ffs_file_selector_api_show_file_chooser_response_new(FlValue* return_value); + +/** + * ffs_file_selector_api_show_file_chooser_response_new_error: + * @code: error code. + * @message: error message. + * @details: (allow-none): error details or %NULL. + * + * Creates a new error response to FileSelectorApi.showFileChooser. + * + * Returns: a new #FfsFileSelectorApiShowFileChooserResponse + */ +FfsFileSelectorApiShowFileChooserResponse* +ffs_file_selector_api_show_file_chooser_response_new_error(const gchar* code, + const gchar* message, + FlValue* details); + +/** + * FfsFileSelectorApiVTable: + * + * Table of functions exposed by FileSelectorApi to be implemented by the API + * provider. + */ +typedef struct { + FfsFileSelectorApiShowFileChooserResponse* (*show_file_chooser)( + FfsPlatformFileChooserActionType type, + FfsPlatformFileChooserOptions* options, gpointer user_data); +} FfsFileSelectorApiVTable; + +/** + * ffs_file_selector_api_set_method_handlers: + * + * @messenger: an #FlBinaryMessenger. + * @suffix: (allow-none): a suffix to add to the API or %NULL for none. + * @vtable: implementations of the methods in this API. + * @user_data: (closure): user data to pass to the functions in @vtable. + * @user_data_free_func: (allow-none): a function which gets called to free + * @user_data, or %NULL. + * + * Connects the method handlers in the FileSelectorApi API. + */ +void ffs_file_selector_api_set_method_handlers( + FlBinaryMessenger* messenger, const gchar* suffix, + const FfsFileSelectorApiVTable* vtable, gpointer user_data, + GDestroyNotify user_data_free_func); + +/** + * ffs_file_selector_api_clear_method_handlers: + * + * @messenger: an #FlBinaryMessenger. + * @suffix: (allow-none): a suffix to add to the API or %NULL for none. + * + * Clears the method handlers in the FileSelectorApi API. + */ +void ffs_file_selector_api_clear_method_handlers(FlBinaryMessenger* messenger, + const gchar* suffix); + +G_END_DECLS + +#endif // PIGEON_MESSAGES_G_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/test/file_selector_plugin_test.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/test/file_selector_plugin_test.cc new file mode 100755 index 00000000..3a3c8459 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/test/file_selector_plugin_test.cc @@ -0,0 +1,242 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "include/file_selector_linux/file_selector_plugin.h" + +#include +#include +#include + +#include "file_selector_plugin_private.h" +#include "messages.g.h" + +// TODO(stuartmorgan): Restructure the helper to take a callback for showing +// the dialog, so that the tests can mock out that callback with something +// that changes the selection so that the return value path can be tested +// as well. +// TODO(stuartmorgan): Add an injectable wrapper around +// gtk_file_chooser_native_new to allow for testing values that are given as +// construction paramaters and can't be queried later. + +// TODO(stuartmorgan): Remove this once +// https://github.com/flutter/flutter/issues/156100 is fixed. For now, this may +// need to be updated to make unit tests pass again any time the +// Pigeon-generated files are updated. +static const int platform_type_group_object_id = 130; + +TEST(FileSelectorPlugin, TestOpenSimple) { + g_autoptr(FfsPlatformFileChooserOptions) options = + ffs_platform_file_chooser_options_new(nullptr, nullptr, nullptr, nullptr, + nullptr); + + g_autoptr(GtkFileChooserNative) dialog = create_dialog_of_type( + nullptr, FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_OPEN, + options); + + ASSERT_NE(dialog, nullptr); + EXPECT_EQ(gtk_file_chooser_get_action(GTK_FILE_CHOOSER(dialog)), + GTK_FILE_CHOOSER_ACTION_OPEN); + EXPECT_EQ(gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog)), + false); +} + +TEST(FileSelectorPlugin, TestOpenMultiple) { + gboolean select_multiple = true; + g_autoptr(FfsPlatformFileChooserOptions) options = + ffs_platform_file_chooser_options_new(nullptr, nullptr, nullptr, nullptr, + &select_multiple); + + g_autoptr(GtkFileChooserNative) dialog = create_dialog_of_type( + nullptr, FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_OPEN, + options); + + ASSERT_NE(dialog, nullptr); + EXPECT_EQ(gtk_file_chooser_get_action(GTK_FILE_CHOOSER(dialog)), + GTK_FILE_CHOOSER_ACTION_OPEN); + EXPECT_EQ(gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog)), + true); +} + +TEST(FileSelectorPlugin, TestOpenWithFilter) { + g_autoptr(FlValue) type_groups = fl_value_new_list(); + + { + g_autoptr(FlValue) text_group_extensions = fl_value_new_list(); + + g_autoptr(FlValue) text_group_mime_types = fl_value_new_list(); + fl_value_append_take(text_group_mime_types, + fl_value_new_string("text/plain")); + + g_autoptr(FfsPlatformTypeGroup) text_group = ffs_platform_type_group_new( + "Text", text_group_extensions, text_group_mime_types); + fl_value_append_take( + type_groups, fl_value_new_custom_object(platform_type_group_object_id, + G_OBJECT(text_group))); + } + + { + g_autoptr(FlValue) image_group_extensions = fl_value_new_list(); + fl_value_append_take(image_group_extensions, fl_value_new_string("*.png")); + fl_value_append_take(image_group_extensions, fl_value_new_string("*.gif")); + fl_value_append_take(image_group_extensions, fl_value_new_string("*.jpeg")); + + g_autoptr(FlValue) image_group_mime_types = fl_value_new_list(); + + g_autoptr(FfsPlatformTypeGroup) image_group = ffs_platform_type_group_new( + "Images", image_group_extensions, image_group_mime_types); + fl_value_append_take( + type_groups, fl_value_new_custom_object(platform_type_group_object_id, + G_OBJECT(image_group))); + } + + { + g_autoptr(FlValue) any_group_extensions = fl_value_new_list(); + fl_value_append_take(any_group_extensions, fl_value_new_string("*")); + + g_autoptr(FlValue) any_group_mime_types = fl_value_new_list(); + + g_autoptr(FfsPlatformTypeGroup) any_group = ffs_platform_type_group_new( + "Any", any_group_extensions, any_group_mime_types); + fl_value_append_take( + type_groups, fl_value_new_custom_object(platform_type_group_object_id, + G_OBJECT(any_group))); + } + + g_autoptr(FfsPlatformFileChooserOptions) options = + ffs_platform_file_chooser_options_new(type_groups, nullptr, nullptr, + nullptr, nullptr); + + g_autoptr(GtkFileChooserNative) dialog = create_dialog_of_type( + nullptr, FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_OPEN, + options); + + ASSERT_NE(dialog, nullptr); + EXPECT_EQ(gtk_file_chooser_get_action(GTK_FILE_CHOOSER(dialog)), + GTK_FILE_CHOOSER_ACTION_OPEN); + EXPECT_EQ(gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog)), + false); + // Validate filters. + g_autoptr(GSList) type_group_list = + gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog)); + EXPECT_EQ(g_slist_length(type_group_list), 3); + GtkFileFilter* text_filter = + GTK_FILE_FILTER(g_slist_nth_data(type_group_list, 0)); + GtkFileFilter* image_filter = + GTK_FILE_FILTER(g_slist_nth_data(type_group_list, 1)); + GtkFileFilter* any_filter = + GTK_FILE_FILTER(g_slist_nth_data(type_group_list, 2)); + // Filters can't be inspected, so query them to see that they match expected + // filter behavior. + GtkFileFilterInfo text_file_info = {}; + text_file_info.contains = static_cast( + GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE); + text_file_info.display_name = "foo.txt"; + text_file_info.mime_type = "text/plain"; + GtkFileFilterInfo image_file_info = {}; + image_file_info.contains = static_cast( + GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE); + image_file_info.display_name = "foo.png"; + image_file_info.mime_type = "image/png"; + EXPECT_TRUE(gtk_file_filter_filter(text_filter, &text_file_info)); + EXPECT_FALSE(gtk_file_filter_filter(text_filter, &image_file_info)); + EXPECT_FALSE(gtk_file_filter_filter(image_filter, &text_file_info)); + EXPECT_TRUE(gtk_file_filter_filter(image_filter, &image_file_info)); + EXPECT_TRUE(gtk_file_filter_filter(any_filter, &image_file_info)); + EXPECT_TRUE(gtk_file_filter_filter(any_filter, &text_file_info)); +} + +TEST(FileSelectorPlugin, TestSaveSimple) { + g_autoptr(FfsPlatformFileChooserOptions) options = + ffs_platform_file_chooser_options_new(nullptr, nullptr, nullptr, nullptr, + nullptr); + + g_autoptr(GtkFileChooserNative) dialog = create_dialog_of_type( + nullptr, FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_SAVE, + options); + + ASSERT_NE(dialog, nullptr); + EXPECT_EQ(gtk_file_chooser_get_action(GTK_FILE_CHOOSER(dialog)), + GTK_FILE_CHOOSER_ACTION_SAVE); + EXPECT_EQ(gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog)), + false); +} + +TEST(FileSelectorPlugin, TestSaveWithArguments) { + g_autoptr(FfsPlatformFileChooserOptions) options = + ffs_platform_file_chooser_options_new(nullptr, "/tmp", "foo.txt", nullptr, + nullptr); + + g_autoptr(GtkFileChooserNative) dialog = create_dialog_of_type( + nullptr, FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_SAVE, + options); + + ASSERT_NE(dialog, nullptr); + EXPECT_EQ(gtk_file_chooser_get_action(GTK_FILE_CHOOSER(dialog)), + GTK_FILE_CHOOSER_ACTION_SAVE); + EXPECT_EQ(gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog)), + false); + g_autofree gchar* current_name = + gtk_file_chooser_get_current_name(GTK_FILE_CHOOSER(dialog)); + EXPECT_STREQ(current_name, "foo.txt"); + // TODO(stuartmorgan): gtk_file_chooser_get_current_folder doesn't seem to + // return a value set by gtk_file_chooser_set_current_folder, or at least + // doesn't in a test context, so that's not currently validated. +} + +TEST(FileSelectorPlugin, TestGetDirectory) { + g_autoptr(FfsPlatformFileChooserOptions) options = + ffs_platform_file_chooser_options_new(nullptr, nullptr, nullptr, nullptr, + nullptr); + + g_autoptr(GtkFileChooserNative) dialog = create_dialog_of_type( + nullptr, + FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_CHOOSE_DIRECTORY, + options); + + ASSERT_NE(dialog, nullptr); + EXPECT_EQ(gtk_file_chooser_get_action(GTK_FILE_CHOOSER(dialog)), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + EXPECT_EQ(gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog)), + false); +} + +TEST(FileSelectorPlugin, TestGetMultipleDirectories) { + gboolean select_multiple = true; + g_autoptr(FfsPlatformFileChooserOptions) options = + ffs_platform_file_chooser_options_new(nullptr, nullptr, nullptr, nullptr, + &select_multiple); + + g_autoptr(GtkFileChooserNative) dialog = create_dialog_of_type( + nullptr, + FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_CHOOSE_DIRECTORY, + options); + + ASSERT_NE(dialog, nullptr); + EXPECT_EQ(gtk_file_chooser_get_action(GTK_FILE_CHOOSER(dialog)), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + EXPECT_EQ(gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog)), + true); +} + +static gint mock_run_dialog_cancel(GtkNativeDialog* dialog) { + return GTK_RESPONSE_CANCEL; +} + +TEST(FileSelectorPlugin, TestGetDirectoryCancel) { + g_autoptr(FfsPlatformFileChooserOptions) options = + ffs_platform_file_chooser_options_new(nullptr, nullptr, nullptr, nullptr, + nullptr); + + g_autoptr(GtkFileChooserNative) dialog = create_dialog_of_type( + nullptr, + FILE_SELECTOR_LINUX_PLATFORM_FILE_CHOOSER_ACTION_TYPE_CHOOSE_DIRECTORY, + options); + + ASSERT_NE(dialog, nullptr); + + g_autoptr(FfsFileSelectorApiShowFileChooserResponse) response = + show_file_chooser(dialog, mock_run_dialog_cancel); + + EXPECT_NE(response, nullptr); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/test/test_main.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/test/test_main.cc new file mode 100755 index 00000000..7e33b21f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/linux/test/test_main.cc @@ -0,0 +1,15 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include + +int main(int argc, char** argv) { + gtk_init(0, nullptr); + + testing::InitGoogleTest(&argc, argv); + int exit_code = RUN_ALL_TESTS(); + + return exit_code; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/pigeons/copyright.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/pigeons/copyright.txt new file mode 100755 index 00000000..1236b63c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/pigeons/messages.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/pigeons/messages.dart new file mode 100755 index 00000000..f10d67cd --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/pigeons/messages.dart @@ -0,0 +1,62 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon(PigeonOptions( + input: 'pigeons/messages.dart', + gobjectHeaderOut: 'linux/messages.g.h', + gobjectSourceOut: 'linux/messages.g.cc', + gobjectOptions: GObjectOptions(module: 'Ffs'), + dartOut: 'lib/src/messages.g.dart', + copyrightHeader: 'pigeons/copyright.txt', +)) + +/// A Pigeon representation of the GTK_FILE_CHOOSER_ACTION_* options. +enum PlatformFileChooserActionType { open, chooseDirectory, save } + +/// A Pigeon representation of the Linux portion of an `XTypeGroup`. +class PlatformTypeGroup { + const PlatformTypeGroup({ + this.label = '', + this.extensions = const [], + this.mimeTypes = const [], + }); + + final String label; + final List extensions; + final List mimeTypes; +} + +/// Options for GKT file chooser. +/// +/// These correspond to gtk_file_chooser_set_* options. +class PlatformFileChooserOptions { + PlatformFileChooserOptions({ + required this.allowedFileTypes, + required this.currentFolderPath, + required this.currentName, + required this.acceptButtonLabel, + this.selectMultiple, + }); + + final List? allowedFileTypes; + final String? currentFolderPath; + final String? currentName; + final String? acceptButtonLabel; + + /// Whether to allow multiple file selection. + /// + /// Nullable because it does not apply to the "save" action. + final bool? selectMultiple; +} + +@HostApi(dartHostTestHandler: 'TestFileSelectorApi') +abstract class FileSelectorApi { + /// Shows an file chooser with the given [type] and [options], returning the + /// list of selected paths. + /// + /// An empty list corresponds to a cancelled selection. + List showFileChooser( + PlatformFileChooserActionType type, PlatformFileChooserOptions options); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/pubspec.yaml new file mode 100755 index 00000000..7284b010 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/pubspec.yaml @@ -0,0 +1,33 @@ +name: file_selector_linux +description: Liunx implementation of the file_selector plugin. +repository: https://github.com/flutter/packages/tree/main/packages/file_selector/file_selector_linux +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+file_selector%22 +version: 0.9.3+2 + +environment: + sdk: ^3.3.0 + flutter: ">=3.19.0" + +flutter: + plugin: + implements: file_selector + platforms: + linux: + pluginClass: FileSelectorPlugin + dartPluginClass: FileSelectorLinux + +dependencies: + cross_file: ^0.3.1 + file_selector_platform_interface: ^2.6.0 + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + pigeon: ^22.6.2 + +topics: + - files + - file-selection + - file-selector diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/test/file_selector_linux_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/test/file_selector_linux_test.dart new file mode 100755 index 00000000..dbf4bcf4 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/file_selector_linux/test/file_selector_linux_test.dart @@ -0,0 +1,417 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_linux/file_selector_linux.dart'; +import 'package:file_selector_linux/src/messages.g.dart'; +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + late FakeFileSelectorApi api; + late FileSelectorLinux plugin; + + setUp(() { + api = FakeFileSelectorApi(); + plugin = FileSelectorLinux(api: api); + }); + + test('registers instance', () { + FileSelectorLinux.registerWith(); + expect(FileSelectorPlatform.instance, isA()); + }); + + group('openFile', () { + test('passes the core flags correctly', () async { + const String path = '/foo/bar'; + api.result = [path]; + + expect((await plugin.openFile())?.path, path); + + expect(api.passedType, PlatformFileChooserActionType.open); + expect(api.passedOptions?.selectMultiple, false); + }); + + test('handles empty return for cancel', () async { + api.result = []; + + expect(await plugin.openFile(), null); + }); + + test('passes the accepted type groups correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + extensions: ['txt'], + mimeTypes: ['text/plain'], + ); + + const XTypeGroup groupTwo = XTypeGroup( + label: 'image', + extensions: ['jpg'], + mimeTypes: ['image/jpg'], + ); + + await plugin.openFile(acceptedTypeGroups: [group, groupTwo]); + + expect(api.passedOptions?.allowedFileTypes?[0].label, group.label); + // Extensions should be converted to *. format. + expect(api.passedOptions?.allowedFileTypes?[0].extensions, + ['*.txt']); + expect( + api.passedOptions?.allowedFileTypes?[0].mimeTypes, group.mimeTypes); + expect(api.passedOptions?.allowedFileTypes?[1].label, groupTwo.label); + expect(api.passedOptions?.allowedFileTypes?[1].extensions, + ['*.jpg']); + expect(api.passedOptions?.allowedFileTypes?[1].mimeTypes, + groupTwo.mimeTypes); + }); + + test('passes initialDirectory correctly', () async { + const String path = '/example/directory'; + await plugin.openFile(initialDirectory: path); + + expect(api.passedOptions?.currentFolderPath, path); + }); + + test('passes confirmButtonText correctly', () async { + const String button = 'Open File'; + await plugin.openFile(confirmButtonText: button); + + expect(api.passedOptions?.acceptButtonLabel, button); + }); + + test('throws for a type group that does not support Linux', () async { + const XTypeGroup group = XTypeGroup( + label: 'images', + webWildCards: ['images/*'], + ); + + await expectLater( + plugin.openFile(acceptedTypeGroups: [group]), + throwsArgumentError); + }); + + test('passes a wildcard group correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'any', + ); + + await plugin.openFile(acceptedTypeGroups: [group]); + + expect(api.passedOptions?.allowedFileTypes?[0].extensions, ['*']); + }); + }); + + group('openFiles', () { + test('passes the core flags correctly', () async { + api.result = ['/foo/bar', 'baz']; + + final List files = await plugin.openFiles(); + + expect(files.length, 2); + expect(files[0].path, api.result[0]); + expect(files[1].path, api.result[1]); + + expect(api.passedType, PlatformFileChooserActionType.open); + expect(api.passedOptions?.selectMultiple, true); + }); + + test('passes the accepted type groups correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + extensions: ['txt'], + mimeTypes: ['text/plain'], + ); + + const XTypeGroup groupTwo = XTypeGroup( + label: 'image', + extensions: ['jpg'], + mimeTypes: ['image/jpg'], + ); + + await plugin.openFiles(acceptedTypeGroups: [group, groupTwo]); + + expect(api.passedOptions?.allowedFileTypes?[0].label, group.label); + // Extensions should be converted to *. format. + expect(api.passedOptions?.allowedFileTypes?[0].extensions, + ['*.txt']); + expect( + api.passedOptions?.allowedFileTypes?[0].mimeTypes, group.mimeTypes); + expect(api.passedOptions?.allowedFileTypes?[1].label, groupTwo.label); + expect(api.passedOptions?.allowedFileTypes?[1].extensions, + ['*.jpg']); + expect(api.passedOptions?.allowedFileTypes?[1].mimeTypes, + groupTwo.mimeTypes); + }); + + test('passes initialDirectory correctly', () async { + const String path = '/example/directory'; + await plugin.openFiles(initialDirectory: path); + + expect(api.passedOptions?.currentFolderPath, path); + }); + + test('passes confirmButtonText correctly', () async { + const String button = 'Open File'; + await plugin.openFiles(confirmButtonText: button); + + expect(api.passedOptions?.acceptButtonLabel, button); + }); + + test('throws for a type group that does not support Linux', () async { + const XTypeGroup group = XTypeGroup( + label: 'images', + webWildCards: ['images/*'], + ); + + await expectLater( + plugin.openFiles(acceptedTypeGroups: [group]), + throwsArgumentError); + }); + + test('passes a wildcard group correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'any', + ); + + await plugin.openFiles(acceptedTypeGroups: [group]); + + expect(api.passedOptions?.allowedFileTypes?[0].extensions, ['*']); + }); + }); + + group('getSaveLocation', () { + test('passes the core flags correctly', () async { + const String path = '/foo/bar'; + api.result = [path]; + + expect((await plugin.getSaveLocation())?.path, path); + + expect(api.passedType, PlatformFileChooserActionType.save); + }); + + test('passes the accepted type groups correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + extensions: ['txt'], + mimeTypes: ['text/plain'], + ); + + const XTypeGroup groupTwo = XTypeGroup( + label: 'image', + extensions: ['jpg'], + mimeTypes: ['image/jpg'], + ); + + await plugin + .getSaveLocation(acceptedTypeGroups: [group, groupTwo]); + + expect(api.passedOptions?.allowedFileTypes?[0].label, group.label); + // Extensions should be converted to *. format. + expect(api.passedOptions?.allowedFileTypes?[0].extensions, + ['*.txt']); + expect( + api.passedOptions?.allowedFileTypes?[0].mimeTypes, group.mimeTypes); + expect(api.passedOptions?.allowedFileTypes?[1].label, groupTwo.label); + expect(api.passedOptions?.allowedFileTypes?[1].extensions, + ['*.jpg']); + expect(api.passedOptions?.allowedFileTypes?[1].mimeTypes, + groupTwo.mimeTypes); + }); + + test('passes initialDirectory correctly', () async { + const String path = '/example/directory'; + await plugin.getSaveLocation( + options: const SaveDialogOptions(initialDirectory: path)); + + expect(api.passedOptions?.currentFolderPath, path); + }); + + test('passes confirmButtonText correctly', () async { + const String button = 'Open File'; + await plugin.getSaveLocation( + options: const SaveDialogOptions(confirmButtonText: button)); + + expect(api.passedOptions?.acceptButtonLabel, button); + }); + + test('throws for a type group that does not support Linux', () async { + const XTypeGroup group = XTypeGroup( + label: 'images', + webWildCards: ['images/*'], + ); + + await expectLater( + plugin.getSaveLocation(acceptedTypeGroups: [group]), + throwsArgumentError); + }); + + test('passes a wildcard group correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'any', + ); + + await plugin.getSaveLocation(acceptedTypeGroups: [group]); + + expect(api.passedOptions?.allowedFileTypes?[0].extensions, ['*']); + }); + }); + + group('getSavePath (deprecated)', () { + test('passes the core flags correctly', () async { + const String path = '/foo/bar'; + api.result = [path]; + + expect(await plugin.getSavePath(), path); + + expect(api.passedType, PlatformFileChooserActionType.save); + }); + + test('passes the accepted type groups correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + extensions: ['txt'], + mimeTypes: ['text/plain'], + ); + + const XTypeGroup groupTwo = XTypeGroup( + label: 'image', + extensions: ['jpg'], + mimeTypes: ['image/jpg'], + ); + + await plugin + .getSavePath(acceptedTypeGroups: [group, groupTwo]); + + expect(api.passedOptions?.allowedFileTypes?[0].label, group.label); + // Extensions should be converted to *. format. + expect(api.passedOptions?.allowedFileTypes?[0].extensions, + ['*.txt']); + expect( + api.passedOptions?.allowedFileTypes?[0].mimeTypes, group.mimeTypes); + expect(api.passedOptions?.allowedFileTypes?[1].label, groupTwo.label); + expect(api.passedOptions?.allowedFileTypes?[1].extensions, + ['*.jpg']); + expect(api.passedOptions?.allowedFileTypes?[1].mimeTypes, + groupTwo.mimeTypes); + }); + + test('passes initialDirectory correctly', () async { + const String path = '/example/directory'; + await plugin.getSavePath(initialDirectory: path); + + expect(api.passedOptions?.currentFolderPath, path); + }); + + test('passes confirmButtonText correctly', () async { + const String button = 'Open File'; + await plugin.getSavePath(confirmButtonText: button); + + expect(api.passedOptions?.acceptButtonLabel, button); + }); + + test('throws for a type group that does not support Linux', () async { + const XTypeGroup group = XTypeGroup( + label: 'images', + webWildCards: ['images/*'], + ); + + await expectLater( + plugin.getSavePath(acceptedTypeGroups: [group]), + throwsArgumentError); + }); + + test('passes a wildcard group correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'any', + ); + + await plugin.getSavePath(acceptedTypeGroups: [group]); + + expect(api.passedOptions?.allowedFileTypes?[0].extensions, ['*']); + }); + }); + + group('getDirectoryPath', () { + test('passes the core flags correctly', () async { + const String path = '/foo/bar'; + api.result = [path]; + + expect(await plugin.getDirectoryPath(), path); + + expect(api.passedType, PlatformFileChooserActionType.chooseDirectory); + expect(api.passedOptions?.selectMultiple, false); + }); + + test('passes initialDirectory correctly', () async { + const String path = '/example/directory'; + await plugin.getDirectoryPath(initialDirectory: path); + + expect(api.passedOptions?.currentFolderPath, path); + }); + + test('passes confirmButtonText correctly', () async { + const String button = 'Select Folder'; + await plugin.getDirectoryPath(confirmButtonText: button); + + expect(api.passedOptions?.acceptButtonLabel, button); + }); + }); + + group('getDirectoryPaths', () { + test('passes the core flags correctly', () async { + api.result = ['/foo/bar', 'baz']; + + expect(await plugin.getDirectoryPaths(), api.result); + + expect(api.passedType, PlatformFileChooserActionType.chooseDirectory); + expect(api.passedOptions?.selectMultiple, true); + }); + + test('passes initialDirectory correctly', () async { + const String path = '/example/directory'; + await plugin.getDirectoryPaths(initialDirectory: path); + + expect(api.passedOptions?.currentFolderPath, path); + }); + + test('passes confirmButtonText correctly', () async { + const String button = 'Select one or mode folders'; + await plugin.getDirectoryPaths(confirmButtonText: button); + + expect(api.passedOptions?.acceptButtonLabel, button); + }); + + test('passes multiple flag correctly', () async { + await plugin.getDirectoryPaths(); + + expect(api.passedOptions?.selectMultiple, true); + }); + }); +} + +/// Fake implementation that stores arguments and provides a canned response. +class FakeFileSelectorApi implements FileSelectorApi { + List result = []; + PlatformFileChooserActionType? passedType; + PlatformFileChooserOptions? passedOptions; + + @override + Future> showFileChooser(PlatformFileChooserActionType type, + PlatformFileChooserOptions options) async { + passedType = type; + passedOptions = options; + return result; + } + + @override + // ignore: non_constant_identifier_names + BinaryMessenger? get pigeonVar_binaryMessenger => null; + + @override + // ignore: non_constant_identifier_names + String get pigeonVar_messageChannelSuffix => ''; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux deleted file mode 120000 index ecdc5940..00000000 --- a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_linux-6.0.0/ \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/CHANGELOG.md b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/CHANGELOG.md new file mode 100755 index 00000000..aade7234 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/CHANGELOG.md @@ -0,0 +1,111 @@ +## [6.0.0] + +* **Breaking change** bumped minimum Flutter SDK requirement to 3.22.0 and Dart SDK requirement to 3.4.0 +* Bumped `flutter_local_notifications_platform_interface` dependency + +## [5.0.0] + +* **Breaking change** Bumped minimum Flutter SDK requirement to 3.13 + +## [4.0.1] + +* Fixed issue [#2368](https://github.com/MaikuB/flutter_local_notifications/issues/2368). This involved updating pubspec so it defines that it implements the Linux implementation of `flutter_local_notifications` and updating the code so it registers the Linux implementation + +## [4.0.0+1] + +* Bumped maximum Dart SDK constraint + +## [4.0.0] + +* **Breaking change** the `id` property of the `ActiveNotification` class is now nullable to help indicate that the notification may not have been created by the plugin e.g. it was from Firebase Cloud Messaging. Thanks to the PR from [frankvollebregt](https://github.com/frankvollebregt) +* **Breaking change** the following classes are now enums + * `LinuxNotificationCategory` + * `LinuxNotificationUrgency` +* Switched from using `mocktail` to `mockito` for consistency and with it getting more updates as a first-party package + +## [3.0.0+1] + +* Bumped `xdg_directories` dependency constraints + +## [3.0.0] + +* Updated minimum Flutter version to 3.0.0. Note that technically this was already a requirement by `flutter_local_notifications_linux` 2.0.0 as `ffi` 2.0.0 requires Dart 2.17 at a minimum and that shipped with Flutter 3.0.0 +* Added explicit `ffi` dependency that plugin was already using + +## [2.0.0] + +* Bumped `dbus` dependency + +## [1.0.0] + +* **Breaking change** The linux notification categories defined by `LinuxNotificationCategory` no longer has factory constructors but has static constant fields instead to make the semantics more similar to access enum values +* Updated minimum Flutter version to 2.8 to align with the minimum Dart SDK version of 2.1.5 required by the `dbus` package + + +## [0.5.1] + +* Fixes issue [1656](https://github.com/MaikuB/flutter_local_notifications/issues/1656) where a version constraint issue occurred with the `path` package. The version constraint has been lowered to resolve the issue + +## [0.5.0+1] + +* Added a note to 0.5.0 changelog to make it clear that the 0.5.0 stable release doesn't have changes from the 0.5.0 pre-releases + +## [0.5.0] + +* Added support for icons to be specified via file path. Thanks to PR from [Yaroslav Pronin](https://github.com/proninyaroslav) +* **Note**: the 0.5.0 release *does not* have the same as what was on the 0.5.0 pre-releases. Those pre-releases are more closely related to changes being done for the 10.0.0 pre-release of `flutter_local_notifications`. What was in the 0.5.0 pre-releases will be shifted to a 1.0.0 pre-release of `flutter_local_notifications_linux` + +## [0.5.0-dev.4] + +* **Breaking change** callbacks have now been reworked. `onDidReceiveNotificationResponse` is invoked only when the app is running. This works for when a user has selected a notification or notification action. This replaces the `onSelectNotification` callback that existed before +* **Breaking change** the `NotificationAppLaunchDetails` has been updated to contain an instance `NotificationResponse` class with the `payload` belonging to the `NotificationResponse` class. This is to allow knowing more details about what caused the app to launch e.g. if a notification action was used to do so + +## [0.5.0-dev.3] + +* Includes changes from 0.4.2 + +## [0.5.0-dev.2] + +* Added support for notification actions + +## [0.5.0-dev.1] + +* Bumped `flutter_local_notifications_platform_interface` dependency + +## [0.4.2] + +* Bumped dependencies. Thanks to PR from [Guy Luz](https://github.com/guyluz11) + +## [0.4.1+1] + +* Fixed minor casing error in 0.4.1 changelog entry + +## [0.4.1] + +* Fix `initialize()` returning null all the time instead of returning an appropriate boolean value to indicate if plugin has been initialised + +## [0.4.0] + +* Bumped `dbus` dependency. + +## [0.3.0] + +* **Breaking change** the `SelectNotificationCallback` typedef now maps to a function that returns `void` instead of a `Future`. This change was done to better communicate the plugin doesn't actually await any asynchronous computation and is similar to how button pressed callbacks work for Flutter where they are typically use [`VoidCallback`](https://api.flutter.dev/flutter/dart-ui/VoidCallback.html) + +## [0.2.0+1] + +* Fixed links to GNOME developer documentation referenced in API docs + +## [0.2.0] + +* Fixed issue when an app using the plugin is built on the web by using conditional imports +* Changed the logic where notification IDs are saved so that `$XDG_RUNTIME_DIR` environment variable is not set but `$TMPDIR` is set, then they are saved to a file within the `/$TMPDIR/APP_NAME/USER_ID/SESSION_ID` directory. If `$TMPDIR` is not set then, it would save to `/tmp/APP_NAME/USER_ID/SESSION_ID` +* Fixed an issue where errors would occur if the plugin was initialised multiple times + +## [0.1.0+1] + +* Point to types within platform interface + +## [0.1.0] + +* Initial version for Linux diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/LICENSE b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/LICENSE new file mode 100755 index 00000000..d666ea44 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/LICENSE @@ -0,0 +1,27 @@ +Copyright 2018 Michael Bui. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/README.md new file mode 100755 index 00000000..9fb2828c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/README.md @@ -0,0 +1,8 @@ +# Flutter Local Notifications Linux plugin + +The Linux implementation of [`flutter_local_notifications`](https://pub.dev/packages/flutter_local_notifications). + +## Usage + +This package is already included as part of the `flutter_local_notifications` package dependency, and will +be included when using `flutter_local_notifications` as normal. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/flutter_local_notifications_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/flutter_local_notifications_linux.dart new file mode 100755 index 00000000..8aeaafb6 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/flutter_local_notifications_linux.dart @@ -0,0 +1,17 @@ +/// The Linux implementation of `flutter_local_notifications`. +library flutter_local_notifications_linux; + +// flutter_local_notifications_linux depends on dbus and posix +// which uses FFI internally; export a stub for platforms that don't +// support FFI (e.g., web) to avoid having transitive dependencies +// break web compilation. +export 'src/flutter_local_notifications_stub.dart' + if (dart.library.ffi) 'src/flutter_local_notifications.dart'; +export 'src/model/capabilities.dart'; +export 'src/model/enums.dart'; +export 'src/model/icon.dart'; +export 'src/model/initialization_settings.dart'; +export 'src/model/location.dart'; +export 'src/model/notification_details.dart'; +export 'src/model/sound.dart'; +export 'src/model/timeout.dart'; diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/dbus_wrapper.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/dbus_wrapper.dart new file mode 100755 index 00000000..95237941 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/dbus_wrapper.dart @@ -0,0 +1,52 @@ +import 'dart:async'; + +import 'package:dbus/dbus.dart'; + +/// Mockable [DBusRemoteObject] wrapper +class DBusWrapper { + late final DBusRemoteObject _object; + late final String _destination; + + /// Build an instance of [DBusRemoteObject] + void build({ + required String destination, + required String path, + }) { + _destination = destination; + _object = DBusRemoteObject( + DBusClient.session(), + name: destination, + path: DBusObjectPath(path), + ); + } + + /// Invokes a method on this [DBusRemoteObject]. + /// Throws [DBusMethodResponseException] if the remote side returns an error. + /// + /// If [replySignature] is provided this causes this method to throw a + /// [DBusReplySignatureException] if the result is successful but the returned + /// values do not match the provided signature. + Future callMethod( + String? interface, + String name, + Iterable values, { + DBusSignature? replySignature, + bool noReplyExpected = false, + bool noAutoStart = false, + bool allowInteractiveAuthorization = false, + }) => + _object.callMethod( + interface, + name, + values, + replySignature: replySignature, + noReplyExpected: noReplyExpected, + noAutoStart: noAutoStart, + allowInteractiveAuthorization: allowInteractiveAuthorization, + ); + + /// Creates a stream of signal with the given [name]. + DBusRemoteObjectSignalStream subscribeSignal(String name) => + DBusRemoteObjectSignalStream( + object: _object, interface: _destination, name: name); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/file_system.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/file_system.dart new file mode 100755 index 00000000..feaa32b2 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/file_system.dart @@ -0,0 +1,14 @@ +import 'dart:io'; + +/// Mockable file system representation +// ignore: one_member_abstracts +abstract class FileSystem { + /// Returns a [File], that referred to the given [path] + File open(String path); +} + +/// A real implementation of [FileSystem] +class LocalFileSystem implements FileSystem { + @override + File open(String path) => File(path); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/flutter_local_notifications.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/flutter_local_notifications.dart new file mode 100755 index 00000000..f7516966 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/flutter_local_notifications.dart @@ -0,0 +1,96 @@ +import 'package:flutter/foundation.dart'; + +import 'flutter_local_notifications_platform_linux.dart'; +import 'model/capabilities.dart'; +import 'model/initialization_settings.dart'; +import 'model/notification_details.dart'; +import 'notifications_manager.dart'; + +/// Linux implementation of the local notifications plugin. +class LinuxFlutterLocalNotificationsPlugin + extends FlutterLocalNotificationsPlatformLinux { + /// Constructs an instance of [LinuxNotificationDetails]. + LinuxFlutterLocalNotificationsPlugin() + : _manager = LinuxNotificationManager(); + + /// Constructs an instance of [LinuxNotificationDetails] + /// with the give [manager]. + @visibleForTesting + LinuxFlutterLocalNotificationsPlugin.private( + LinuxNotificationManager manager, + ) : _manager = manager; + + /// Registers the Linux implementation. + static void registerWith() { + FlutterLocalNotificationsPlatform.instance = + LinuxFlutterLocalNotificationsPlugin(); + } + + final LinuxNotificationManager _manager; + + /// Initializes the plugin. + /// + /// Call this method on application before using the plugin further. + /// + /// This should only be done once. When a notification created by this plugin + /// was used to launch the app, calling [initialize] is what will trigger to + /// the [onSelectNotification] callback to be fire. + /// + /// [onSelectNotificationAction] specifies a callback handler which receives + /// notification action IDs. + @override + Future initialize( + LinuxInitializationSettings initializationSettings, { + DidReceiveNotificationResponseCallback? onDidReceiveNotificationResponse, + }) => + _manager.initialize( + initializationSettings, + onDidReceiveNotificationResponse: onDidReceiveNotificationResponse, + ); + + /// Show a notification with an optional payload that will be passed back to + /// the app when a notification is tapped on. + @override + Future show( + int id, + String? title, + String? body, { + LinuxNotificationDetails? notificationDetails, + String? payload, + }) { + validateId(id); + return _manager.show( + id, + title, + body, + details: notificationDetails, + payload: payload, + ); + } + + @override + Future cancel(int id) { + validateId(id); + return _manager.cancel(id); + } + + @override + Future cancelAll() => _manager.cancelAll(); + + /// Returns the system notification server capabilities. + /// Some functionality may not be implemented by the notification server, + /// conforming clients should check if it is available before using it. + @override + Future getCapabilities() => + _manager.getCapabilities(); + + /// Returns a [Map] with the specified notification id as the key + /// and the id, assigned by the system, as the value. + /// + /// Note: the system ID is unique only within the current user session, + /// so it's undesirable to save it to persistable storage without any + /// invalidation/update. For more information, please see + /// Desktop Notifications Specification https://specifications.freedesktop.org/notification-spec/latest/ar01s02.html + @override + Future> getSystemIdMap() => _manager.getSystemIdMap(); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/flutter_local_notifications_platform_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/flutter_local_notifications_platform_linux.dart new file mode 100755 index 00000000..04adc5fa --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/flutter_local_notifications_platform_linux.dart @@ -0,0 +1,48 @@ +import 'package:flutter_local_notifications_platform_interface/flutter_local_notifications_platform_interface.dart'; + +import 'model/capabilities.dart'; +import 'model/initialization_settings.dart'; +import 'model/notification_details.dart'; + +export 'package:flutter_local_notifications_platform_interface/flutter_local_notifications_platform_interface.dart'; + +/// The interface that all implementations of flutter_local_notifications_linux +/// must implement. +abstract class FlutterLocalNotificationsPlatformLinux + extends FlutterLocalNotificationsPlatform { + /// Initializes the plugin. + /// + /// Call this method on application before using the plugin further. + /// + /// The [onDidReceiveNotificationResponse] callback is fired when the user + /// selects a notification or notification action. + Future initialize( + LinuxInitializationSettings initializationSettings, { + DidReceiveNotificationResponseCallback? onDidReceiveNotificationResponse, + }); + + /// Show a notification with an optional payload that will be passed back to + /// the app when a notification is tapped on. + @override + Future show( + int id, + String? title, + String? body, { + LinuxNotificationDetails? notificationDetails, + String? payload, + }); + + /// Returns the system notification server capabilities. + /// Some functionality may not be implemented by the notification server, + /// conforming clients should check if it is available before using it. + Future getCapabilities(); + + /// Returns a [Map] with the specified notification id as the key + /// and the id, assigned by the system, as the value. + /// + /// Note: the system ID is unique only within the current user session, + /// so it's undesirable to save it to persistable storage without any + /// invalidation/update. For more information, please see + /// Desktop Notifications Specification https://specifications.freedesktop.org/notification-spec/latest/ar01s02.html + Future> getSystemIdMap(); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/flutter_local_notifications_stub.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/flutter_local_notifications_stub.dart new file mode 100755 index 00000000..859a6a80 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/flutter_local_notifications_stub.dart @@ -0,0 +1,60 @@ +import 'flutter_local_notifications_platform_linux.dart'; +import 'model/capabilities.dart'; +import 'model/initialization_settings.dart'; +import 'model/notification_details.dart'; + +/// A stub implementation to satisfy compilation of multi-platform packages that +/// depend on flutter_local_notifications_linux. +/// This should never actually be created. +/// +/// Notably, because flutter_local_notifications needs to manually register +/// flutter_local_notifications_linux, anything with a transitive dependency on +/// flutter_local_notifications will also depend on +/// flutter_local_notifications_linux, not just at +/// the pubspec level but the code level. +class LinuxFlutterLocalNotificationsPlugin + extends FlutterLocalNotificationsPlatformLinux { + /// Errors on attempted instantiation of the stub. It exists only to satisfy + /// compile-time dependencies, and should never actually be created. + LinuxFlutterLocalNotificationsPlugin() : assert(false); + + /// Errors on attempted calling of the stub. It exists only to satisfy + /// compile-time dependencies, and should never actually be called. + @override + Future initialize( + LinuxInitializationSettings initializationSettings, { + DidReceiveNotificationResponseCallback? onDidReceiveNotificationResponse, + }) async { + assert(false); + return null; + } + + /// Errors on attempted calling of the stub. It exists only to satisfy + /// compile-time dependencies, and should never actually be called. + @override + Future show( + int id, + String? title, + String? body, { + LinuxNotificationDetails? notificationDetails, + String? payload, + }) async { + assert(false); + } + + /// Errors on attempted calling of the stub. It exists only to satisfy + /// compile-time dependencies, and should never actually be called. + @override + Future getCapabilities() async { + assert(false); + throw UnimplementedError(); + } + + /// Errors on attempted calling of the stub. It exists only to satisfy + /// compile-time dependencies, and should never actually be called. + @override + Future> getSystemIdMap() async { + assert(false); + throw UnimplementedError(); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/helpers.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/helpers.dart new file mode 100755 index 00000000..ef2c9503 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/helpers.dart @@ -0,0 +1,61 @@ +import 'package:dbus/dbus.dart'; + +import 'model/enums.dart'; +import 'model/hint.dart'; + +/// [LinuxHintValue] utils. +extension LinuxHintValueExtension on LinuxHintValue { + /// Convert value to [DBusValue]. + DBusValue toDBusValue() { + switch (type) { + case LinuxHintValueType.array: + final List l = value as List; + return DBusArray( + l.first.toDBusValue().signature, + l.map((LinuxHintValue v) => v.toDBusValue()), + ); + case LinuxHintValueType.boolean: + return DBusBoolean(value); + case LinuxHintValueType.byte: + return DBusByte(value); + case LinuxHintValueType.dict: + final Map m = + value as Map; + return DBusDict( + m.keys.first.toDBusValue().signature, + m.values.first.toDBusValue().signature, + m.map( + (LinuxHintValue key, LinuxHintValue value) => + MapEntry( + key.toDBusValue(), + value.toDBusValue(), + ), + ), + ); + case LinuxHintValueType.double: + return DBusDouble(value); + case LinuxHintValueType.int16: + return DBusInt16(value); + case LinuxHintValueType.int32: + return DBusInt32(value); + case LinuxHintValueType.int64: + return DBusInt64(value); + case LinuxHintValueType.string: + return DBusString(value); + case LinuxHintValueType.struct: + return DBusStruct( + (value as List).map( + (LinuxHintValue v) => v.toDBusValue(), + ), + ); + case LinuxHintValueType.uint16: + return DBusUint16(value); + case LinuxHintValueType.uint32: + return DBusUint32(value); + case LinuxHintValueType.uint64: + return DBusUint64(value); + case LinuxHintValueType.variant: + return DBusVariant((value as LinuxHintValue).toDBusValue()); + } + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/capabilities.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/capabilities.dart new file mode 100755 index 00000000..880f6f32 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/capabilities.dart @@ -0,0 +1,154 @@ +import 'package:flutter/foundation.dart'; + +import 'initialization_settings.dart'; +import 'notification_details.dart'; +import 'sound.dart'; + +/// Represents capabilities, implemented by the Linux notification server. +@immutable +class LinuxServerCapabilities { + /// Constructs an instance of [LinuxServerCapabilities] + const LinuxServerCapabilities({ + required this.otherCapabilities, + required this.body, + required this.bodyHyperlinks, + required this.bodyImages, + required this.bodyMarkup, + required this.iconMulti, + required this.iconStatic, + required this.persistence, + required this.sound, + required this.actions, + required this.actionIcons, + }); + + /// Set of unknown capabilities. + /// Vendor-specific capabilities may be specified as long as they start with + /// `x-vendor`. For example, `x-gnome-foo-cap`. Capability names must not + /// contain spaces. They are limited to alpha-numeric characters and + /// dashes ("-") + final Set otherCapabilities; + + /// Supports body text. Some implementations may only show the title + /// (for instance, onscreen displays, marquee/scrollers). + final bool body; + + /// The server supports hyperlinks in the notifications. + final bool bodyHyperlinks; + + /// The server supports images in the notifications. + final bool bodyImages; + + /// Supports markup in the body text. The markup is XML-based, and consists + /// of a small subset of HTML along with a few additional tags. + /// For more information, see Desktop Notifications Specification https://specifications.freedesktop.org/notification-spec/latest/ar01s04.html + /// If marked up text is sent to a server + /// that does not give this cap, the markup will show through as regular text + /// so must be stripped clientside. + final bool bodyMarkup; + + /// The server will render an animation of all the frames in a given + /// image array. The client may still specify multiple frames even if this + /// cap and/or [iconStatic] is missing, however the server is free to ignore + /// them and use only the primary frame. + final bool iconMulti; + + /// Supports display of exactly 1 frame of any given image array. + /// This value is mutually exclusive with [iconMulti], it is a protocol + /// error for the server to specify both. + final bool iconStatic; + + /// The server supports persistence of notifications. Notifications will be + /// retained until they are acknowledged or removed by the user or + /// recalled by the sender. The presence of this capability allows clients to + /// depend on the server to ensure a notification is seen and eliminate + /// the need for the client to display a reminding function + /// (such as a status icon) of its own. + final bool persistence; + + /// The server supports sounds on notifications. If returned, the server must + /// support the [AssetsLinuxSound], [LinuxNotificationDetails.suppressSound] + /// and [LinuxInitializationSettings.defaultSuppressSound]. + final bool sound; + + /// The server will provide the specified actions to the user. + /// Even if this capability is missing, actions may still be specified by the + /// client, however the server is free to ignore them. + final bool actions; + + /// Supports using icons instead of text for displaying actions. + /// Using icons for actions must be enabled on a per-notification basis using + /// [LinuxNotificationDetails.actionKeyAsIconName]. + final bool actionIcons; + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + + return other is LinuxServerCapabilities && + setEquals(other.otherCapabilities, otherCapabilities) && + other.body == body && + other.bodyHyperlinks == bodyHyperlinks && + other.bodyImages == bodyImages && + other.bodyMarkup == bodyMarkup && + other.iconMulti == iconMulti && + other.iconStatic == iconStatic && + other.persistence == persistence && + other.sound == sound && + other.actions == actions && + other.actionIcons == actionIcons; + } + + @override + int get hashCode => + otherCapabilities.hashCode ^ + body.hashCode ^ + bodyHyperlinks.hashCode ^ + bodyImages.hashCode ^ + bodyMarkup.hashCode ^ + iconMulti.hashCode ^ + iconStatic.hashCode ^ + persistence.hashCode ^ + sound.hashCode ^ + actions.hashCode ^ + actionIcons.hashCode; + + /// Creates a copy of this object, + /// but with the given fields replaced with the new values. + LinuxServerCapabilities copyWith({ + Set? otherCapabilities, + bool? body, + bool? bodyHyperlinks, + bool? bodyImages, + bool? bodyMarkup, + bool? iconMulti, + bool? iconStatic, + bool? persistence, + bool? sound, + bool? actions, + bool? actionIcons, + }) => + LinuxServerCapabilities( + otherCapabilities: otherCapabilities ?? this.otherCapabilities, + body: body ?? this.body, + bodyHyperlinks: bodyHyperlinks ?? this.bodyHyperlinks, + bodyImages: bodyImages ?? this.bodyImages, + bodyMarkup: bodyMarkup ?? this.bodyMarkup, + iconMulti: iconMulti ?? this.iconMulti, + iconStatic: iconStatic ?? this.iconStatic, + persistence: persistence ?? this.persistence, + sound: sound ?? this.sound, + actions: actions ?? this.actions, + actionIcons: actionIcons ?? this.actionIcons, + ); + + @override + String toString() => 'LinuxServerCapabilities(otherCapabilities: ' + '$otherCapabilities, body: $body, bodyHyperlinks: $bodyHyperlinks, ' + 'bodyImages: $bodyImages, bodyMarkup: $bodyMarkup, ' + 'iconMulti: $iconMulti, iconStatic: $iconStatic, ' + 'persistence: $persistence, sound: $sound, actions: $actions, ' + 'actionIcons: $actionIcons)'; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/enums.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/enums.dart new file mode 100755 index 00000000..5dc3fa94 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/enums.dart @@ -0,0 +1,167 @@ +import 'icon.dart'; + +/// Categories of notifications. +/// +/// Corresponds to https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html#categories +enum LinuxNotificationCategory { + /// A generic device-related notification + /// that doesn't fit into any other category. + device('device'), + + /// A device, such as a USB device, was added to the system. + deviceAdded('device.added'), + + /// A device had some kind of error. + deviceError('device.error'), + + /// A device, such as a USB device, was removed from the system. + deviceRemoved('device.removed'), + + /// A generic e-mail-related notification + /// that doesn't fit into any other category. + email('email'), + + /// A new e-mail notification. + emailArrived('email.arrived'), + + /// A notification stating that an e-mail has bounced. + emailBounced('email.bounced'), + + /// A generic instant message-related notification + /// that doesn't fit into any other + im('im'), + + /// An instant message error notification. + imError('im.error'), + + /// A received instant message notification. + imReceived('im.received'), + + /// A generic network notification that + /// doesn't fit into any other category. + network('network'), + + /// A network connection notification, + /// such as successful sign-on to a network service. + /// This should not be confused with + /// [deviceAdded] for new network devices. + networkConnected('network.connected'), + + /// A network disconnected notification. + /// This should not be confused with [deviceRemoved] + /// for disconnected network devices. + networkDisconnected('network.disconnected'), + + /// A network-related or connection-related error. + networkError('network.error'), + + /// A generic presence change notification + /// that doesn't fit into any other category, such as going away or idle. + presence('presence'), + + /// An offline presence change notification. + presenceOffile('presence.offline'), + + /// An online presence change notification. + presenceOnline('presence.online'), + + /// A generic file transfer or download notification + /// that doesn't fit into any other category. + transfer('transfer'), + + /// A file transfer or download complete notification. + transferComplete('transfer.complete'), + + /// A file transfer or download error. + transferError('transfer.error'); + + /// Constructs an instance of [LinuxNotificationCategory] + /// with a given [name] of category. + const LinuxNotificationCategory(this.name); + + /// Name of category. + final String name; +} + +/// The urgency level of the Linux notification. +/// +/// Corresponds to https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html#urgency-levels +enum LinuxNotificationUrgency { + /// Low urgency. Used for unimportant notifications. + low, + + /// Normal urgency. Used for most standard notifications. + normal, + + /// Critical urgency. Used for very important notifications. + critical +} + +/// Specifies the Linux notification icon type. +enum LinuxIconType { + /// Icon from the Flutter Assets directory, see [AssetsLinuxIcon] + assets, + + /// Icon from a raw image data bytes, see [ByteDataLinuxIcon]. + byteData, + + /// System theme icon, see [ThemeLinuxIcon]. + theme, + + /// Icon located at the path in the file system, see [FilePathLinuxIcon]. + filePath, +} + +/// Specifies the Linux notification sound type. +enum LinuxSoundType { + /// Sound from the Flutter Assets directory, see [AssetsLinuxSound] + assets, + + /// System theme sound, see [ThemeLinuxSound]. + theme, +} + +/// Represents the notification hint value type. +enum LinuxHintValueType { + /// Ordered list of values of the same type. + array, + + /// Boolean value. + boolean, + + /// Unsigned 8 bit value. + byte, + + /// Associative array of values. + dict, + + /// 64-bit floating point value. + double, + + /// Signed 16-bit integer. + int16, + + /// Signed 32-bit integer. + int32, + + /// Signed 64-bit integer. + int64, + + /// Unicode text string. + string, + + /// Value that contains a fixed set of other values. + struct, + + /// Unsigned 16-bit integer. + uint16, + + /// Unsigned 32-bit integer. + uint32, + + /// Unsigned 64-bit integer. + uint64, + + /// Value that contains any type. + variant, +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/hint.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/hint.dart new file mode 100755 index 00000000..60c27d44 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/hint.dart @@ -0,0 +1,209 @@ +import 'package:flutter/foundation.dart'; + +import 'enums.dart'; + +/// Represents a custom Linux notification hint. +/// Hints are a way to provide extra data to a notification server that +/// the server may be able to make use of. +/// For more information, please see Desktop Notifications Specification https://specifications.freedesktop.org/notification-spec/latest/ar01s08.html +@optionalTypeArgs +class LinuxNotificationCustomHint { + /// Constructs an instance of [LinuxNotificationCustomHint]. + const LinuxNotificationCustomHint(this.name, this.value); + + /// Name of this hint. + /// The vendor hint name should be in the form of `x-vendor-name`. + final String name; + + /// Value corresponding to the hint. + final LinuxHintValue value; +} + +/// Represents abstract Linux notification hint value. +@optionalTypeArgs +abstract class LinuxHintValue { + /// Specifies the notification hint value type. + LinuxHintValueType get type; + + /// Value, corresponding to the Dart type system. + T get value; +} + +/// Ordered list of values of the same type. +class LinuxHintArrayValue + implements LinuxHintValue> { + /// Constructs an instance of [LinuxHintArrayValue]. + const LinuxHintArrayValue(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.array; + + @override + final List value; +} + +/// Boolean value. +class LinuxHintBoolValue extends LinuxHintValue { + /// Constructs an instance of [LinuxHintBoolValue]. + LinuxHintBoolValue(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.boolean; + + @override + final bool value; +} + +/// Unsigned 8 bit value. +class LinuxHintByteValue extends LinuxHintValue { + /// Constructs an instance of [LinuxHintByteValue]. + LinuxHintByteValue(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.byte; + + @override + final int value; +} + +/// Associative array of values. +class LinuxHintDictValue + extends LinuxHintValue> { + /// Constructs an instance of [LinuxHintDictValue]. + LinuxHintDictValue(this.value); + + /// Constructs an instance of [LinuxHintDictValue]. + LinuxHintDictValue.stringVariant(Map value) + : value = value.map( + (String key, V value) => MapEntry( + LinuxHintStringValue(key) as K, + value, + ), + ); + + @override + LinuxHintValueType get type => LinuxHintValueType.dict; + + @override + final Map value; +} + +/// 64-bit floating point value. +class LinuxHintDoubleValue extends LinuxHintValue { + /// Constructs an instance of [LinuxHintDoubleValue]. + LinuxHintDoubleValue(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.double; + + @override + final double value; +} + +/// Signed 16-bit integer. +class LinuxHintInt16Value extends LinuxHintValue { + /// Constructs an instance of [LinuxHintInt16Value]. + LinuxHintInt16Value(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.int16; + + @override + final int value; +} + +/// Signed 32-bit integer. +class LinuxHintInt32Value extends LinuxHintValue { + /// Constructs an instance of [LinuxHintInt32Value]. + LinuxHintInt32Value(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.int32; + + @override + final int value; +} + +/// Signed 64-bit integer. +class LinuxHintInt64Value extends LinuxHintValue { + /// Constructs an instance of [LinuxHintInt64Value]. + LinuxHintInt64Value(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.int64; + + @override + final int value; +} + +/// Unicode text string. +class LinuxHintStringValue extends LinuxHintValue { + /// Constructs an instance of [LinuxHintStringValue]. + LinuxHintStringValue(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.string; + + @override + final String value; +} + +/// Value that contains a fixed set of other values. +class LinuxHintStructValue extends LinuxHintValue> { + /// Constructs an instance of [LinuxHintStructValue]. + LinuxHintStructValue(Iterable value) : value = value.toList(); + + @override + LinuxHintValueType get type => LinuxHintValueType.struct; + + @override + final List value; +} + +/// Unsigned 16-bit integer. +class LinuxHintUint16Value extends LinuxHintValue { + /// Constructs an instance of [LinuxHintUint16Value]. + LinuxHintUint16Value(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.uint16; + + @override + final int value; +} + +/// Unsigned 32-bit integer. +class LinuxHintUint32Value extends LinuxHintValue { + /// Constructs an instance of [LinuxHintUint32Value]. + LinuxHintUint32Value(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.uint32; + + @override + final int value; +} + +/// Unsigned 64-bit integer. +class LinuxHintUint64Value extends LinuxHintValue { + /// Constructs an instance of [LinuxHintUint64Value]. + LinuxHintUint64Value(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.uint64; + + @override + final int value; +} + +/// Value that contains any type. +class LinuxHintVariantValue extends LinuxHintValue { + /// Constructs an instance of [LinuxHintVariantValue]. + LinuxHintVariantValue(this.value); + + @override + LinuxHintValueType get type => LinuxHintValueType.variant; + + @override + final LinuxHintValue value; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/icon.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/icon.dart new file mode 100755 index 00000000..76ce1543 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/icon.dart @@ -0,0 +1,114 @@ +import 'dart:typed_data'; + +import 'enums.dart'; + +/// Represents Linux notification icon. +abstract class LinuxNotificationIcon { + /// Implementation-defined icon content. + Object get content; + + /// Defines the type of icon. + LinuxIconType get type; +} + +/// Represents an icon from the Flutter Assets directory. +/// Currently the assets directory is `data/flutter_assets` +/// which is located on the path relative to the executable file. +class AssetsLinuxIcon extends LinuxNotificationIcon { + /// Constructs an instance of [AssetsLinuxIcon]. + AssetsLinuxIcon(this.relativePath); + + @override + Object get content => relativePath; + + @override + LinuxIconType get type => LinuxIconType.assets; + + /// Icon relative path inside the Flutter Assets directory + final String relativePath; +} + +/// Represents an icon from a raw image data bytes, see [LinuxRawIconData]. +class ByteDataLinuxIcon extends LinuxNotificationIcon { + /// Constructs an instance of [ByteDataLinuxIcon]. + ByteDataLinuxIcon(this.iconData); + + @override + Object get content => iconData; + + @override + LinuxIconType get type => LinuxIconType.byteData; + + /// Icon data + final LinuxRawIconData iconData; +} + +/// Represents a system theme icon. +/// See https://www.freedesktop.org/wiki/Specifications/icon-naming-spec/ for more help. +class ThemeLinuxIcon extends LinuxNotificationIcon { + /// Constructs an instance of [ThemeLinuxIcon]. + ThemeLinuxIcon(this.name); + + @override + Object get content => name; + + @override + LinuxIconType get type => LinuxIconType.theme; + + /// Name in a freedesktop.org-compliant icon theme (not a GTK+ stock ID). + final String name; +} + +/// Represents an icon in the raw image data. +class LinuxRawIconData { + /// Constructs an instance of [LinuxRawIconData]. + LinuxRawIconData({ + required this.data, + required this.width, + required this.height, + int? rowStride, + this.bitsPerSample = 8, + this.channels = 3, + this.hasAlpha = false, + }) : rowStride = rowStride ?? ((width * channels * bitsPerSample) / 8).ceil(); + + /// Raw data (decoded from the image format) for the image in bytes. + final Uint8List data; + + /// Width of the image in pixels + final int width; + + /// Height of the image in pixels + final int height; + + /// The number of bytes per row in [data] + final int rowStride; + + /// The number of bits in each color sample + final int bitsPerSample; + + /// The number of channels in the image (e.g. 3 for RGB, 4 for RGBA). + /// If [hasAlpha] is `true`, must be 4. + final int channels; + + /// Determines if the image has an alpha channel + final bool hasAlpha; +} + +/// Represents an icon located at the path in the file system. +/// It сan be either an absolute UNIX path or a file:// URI scheme, for example: +/// * file:///usr/share/icons/my_icon.png +/// * /usr/share/icons/my_icon.png +class FilePathLinuxIcon extends LinuxNotificationIcon { + /// Constructs an instance of [FilePathLinuxIcon]. + FilePathLinuxIcon(this.path); + + @override + Object get content => path; + + @override + LinuxIconType get type => LinuxIconType.filePath; + + /// Path to the icon + final String path; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/initialization_settings.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/initialization_settings.dart new file mode 100755 index 00000000..cd10aefc --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/initialization_settings.dart @@ -0,0 +1,30 @@ +import 'icon.dart'; +import 'sound.dart'; + +/// Plugin initialization settings for Linux. +class LinuxInitializationSettings { + /// Constructs an instance of [LinuxInitializationSettings] + const LinuxInitializationSettings({ + required this.defaultActionName, + this.defaultIcon, + this.defaultSound, + this.defaultSuppressSound = false, + }); + + /// Name of the default action (usually triggered by clicking + /// the notification). + /// The name can be anything, though implementations are free not to + /// display it. + final String defaultActionName; + + /// Specifies the default icon for notifications. + final LinuxNotificationIcon? defaultIcon; + + /// Specifies the default sound for notifications. + /// Typical value is `ThemeLinuxSound('message')` + final LinuxNotificationSound? defaultSound; + + /// Causes the server to suppress playing any sounds, if it has that ability. + /// This is usually set when the client itself is going to play its own sound. + final bool defaultSuppressSound; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/location.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/location.dart new file mode 100755 index 00000000..bfbb9216 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/location.dart @@ -0,0 +1,39 @@ +import 'package:flutter/foundation.dart'; + +/// Represents the location on the screen that the notification should point to. +@immutable +class LinuxNotificationLocation { + /// Constructs an instance of [LinuxNotificationLocation] + const LinuxNotificationLocation(this.x, this.y); + + /// Represents the `X` location on the screen that the notification + /// should point to. + final int x; + + /// Represents the `Y` location on the screen that the notification + /// should point to. + final int y; + + /// Creates a copy of this object, + /// but with the given fields replaced with the new values. + LinuxNotificationLocation copyWith({ + int? x, + int? y, + }) => + LinuxNotificationLocation(x ?? this.x, y ?? this.y); + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + + return other is LinuxNotificationLocation && other.x == x && other.y == y; + } + + @override + int get hashCode => x.hashCode ^ y.hashCode; + + @override + String toString() => 'LinuxNotificationLocation(x: $x, y: $y)'; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/notification_details.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/notification_details.dart new file mode 100755 index 00000000..8898c9ed --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/notification_details.dart @@ -0,0 +1,120 @@ +import 'capabilities.dart'; +import 'enums.dart'; +import 'hint.dart'; +import 'icon.dart'; +import 'location.dart'; +import 'sound.dart'; +import 'timeout.dart'; + +/// Configures notification details specific to Linux. +/// The system may not support all features. +class LinuxNotificationDetails { + /// Constructs an instance of [LinuxNotificationDetails]. + const LinuxNotificationDetails({ + this.icon, + this.sound, + this.category, + this.urgency, + this.timeout = const LinuxNotificationTimeout.systemDefault(), + this.resident = false, + this.suppressSound = false, + this.transient = false, + this.location, + this.defaultActionName, + this.customHints, + this.actions = const [], + this.actionKeyAsIconName = false, + }); + + /// Specifies the notification icon. + final LinuxNotificationIcon? icon; + + /// Specifies the notification sound. + /// Typical value is `ThemeLinuxSound('message')` + final LinuxNotificationSound? sound; + + /// Specifies the category for notification. + /// This can be used by the notification server to filter or + /// display the data in a certain way. + final LinuxNotificationCategory? category; + + /// Sets the urgency level for notification. + final LinuxNotificationUrgency? urgency; + + /// Sets the timeout for notification. + /// To set the default time, pass [LinuxNotificationTimeout.systemDefault] + /// value. To set the notification to never expire, + /// pass [LinuxNotificationTimeout.expiresNever]. + /// + /// Note that the timeout may be ignored by the server. + final LinuxNotificationTimeout timeout; + + /// When set the server will not automatically remove the notification + /// when an action has been invoked. The notification will remain resident in + /// the server until it is explicitly removed by the user or by the sender. + /// This option is likely only useful when the server has + /// the [LinuxServerCapabilities.persistence] capability. + final bool resident; + + /// Causes the server to suppress playing any sounds, if it has that ability. + /// This is usually set when the client itself is going to play its own sound. + final bool suppressSound; + + /// When set the server will treat the notification as transient and + /// by-pass the server's [LinuxServerCapabilities.persistence] capability, + /// if it should exist. + final bool transient; + + /// Specifies the location on the screen that the notification + /// should point to. + final LinuxNotificationLocation? location; + + /// Name of the default action (usually triggered by clicking + /// the notification). + /// The name can be anything, though implementations are free not to + /// display it. + final String? defaultActionName; + + /// Custom hints list to provide extra data to a notification server that + /// the server may be able to make use of. Before using, make sure that + /// the server supports this capability, please see [LinuxServerCapabilities]. + final List? customHints; + + /// Specify a list of actions associated with this notifications. + final List actions; + + /// If `true`, the server will attempt to interpret + /// [LinuxNotificationAction.key] as a named icon. + /// [LinuxNotificationAction.label] will be used to annotate the icon for + /// accessibility purposes. The icon name should be compliant with the + /// Freedesktop.org Icon Naming Specification https://specifications.freedesktop.org/icon-naming-spec/latest/ + /// + /// Note: before using, make sure that the server supports this capability, + /// please see [LinuxServerCapabilities]. + final bool actionKeyAsIconName; +} + +/// Represents an action, that send a request message back to the notification +/// client when invoked. This functionality may not be implemented by the +/// notification server, conforming clients should check if it's available using +/// [LinuxServerCapabilities]. +/// For more information, please see Desktop Notifications Specification https://specifications.freedesktop.org/notification-spec/latest/ar01s02.html +class LinuxNotificationAction { + /// Constructs a [LinuxNotificationAction] object. + const LinuxNotificationAction({ + required this.key, + required this.label, + }); + + /// Unique ID for this action. This ID will be sent back in the action handler + /// defined in [FlutterLocalNotificationsPlugin]. + /// + /// If [LinuxNotificationDetails.keyAsIconName] is `true`, + /// the server will attempt to interpret [key] as a named icon. + /// [label] will be used to annotate the icon for accessibility purposes. + /// The icon name should be compliant with the Freedesktop.org Icon Naming Specification https://specifications.freedesktop.org/icon-naming-spec/latest/ + final String key; + + /// Label to show to the user. + final String label; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/sound.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/sound.dart new file mode 100755 index 00000000..b0581da5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/sound.dart @@ -0,0 +1,42 @@ +import 'enums.dart'; + +/// Represents Linux notification sound. +abstract class LinuxNotificationSound { + /// Implementation-defined sound content. + Object get content; + + /// Defines the type of sound. + LinuxSoundType get type; +} + +/// Represents a sound from the Flutter Assets directory. +class AssetsLinuxSound extends LinuxNotificationSound { + /// Constructs an instance of [AssetsLinuxSound]. + AssetsLinuxSound(this.relativePath); + + @override + Object get content => relativePath; + + @override + LinuxSoundType get type => LinuxSoundType.assets; + + /// Sound relative path inside the Flutter Assets directory + final String relativePath; +} + +/// Represents a system theme sound. +/// See https://www.freedesktop.org/wiki/Specifications/sound-theme-spec/ for more help. +class ThemeLinuxSound extends LinuxNotificationSound { + /// Constructs an instance of [ThemeLinuxSound]. + ThemeLinuxSound(this.name); + + @override + Object get content => name; + + @override + LinuxSoundType get type => LinuxSoundType.theme; + + /// A themeable named sound from the + /// freedesktop.org sound naming specification http://0pointer.de/public/sound-naming-spec.html + final String name; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/timeout.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/timeout.dart new file mode 100755 index 00000000..ff239290 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/model/timeout.dart @@ -0,0 +1,41 @@ +import 'package:flutter/foundation.dart'; + +/// The timeout of the Linux notification. +@immutable +class LinuxNotificationTimeout { + /// Constructs an instance of [LinuxNotificationTimeout] + /// with a given [value] in milliseconds. + const LinuxNotificationTimeout(this.value); + + /// Constructs an instance of [LinuxNotificationTimeout] + /// with a given [Duration] value. + LinuxNotificationTimeout.fromDuration(Duration duration) + : value = duration.inMilliseconds; + + /// Constructs an instance of [LinuxNotificationTimeout] + /// with a [value] equal to `-1`. + /// The system default timeout value will be used. + const LinuxNotificationTimeout.systemDefault() : value = -1; + + /// Constructs an instance of [LinuxNotificationTimeout] + /// with a [value] equal to `0`. The notification will be never expires. + const LinuxNotificationTimeout.expiresNever() : value = 0; + + /// The integer representation in milliseconds. + final int value; + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + + return other is LinuxNotificationTimeout && other.value == value; + } + + @override + int get hashCode => value.hashCode; + + @override + String toString() => 'LinuxNotificationTimeout(value: $value)'; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/notification_info.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/notification_info.dart new file mode 100755 index 00000000..b89d9afb --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/notification_info.dart @@ -0,0 +1,123 @@ +import 'package:flutter/foundation.dart'; + +/// Represents a Linux notification information +@immutable +class LinuxNotificationInfo { + /// Constructs an instance of [LinuxPlatformInfoData]. + const LinuxNotificationInfo({ + required this.id, + required this.systemId, + this.payload, + this.actions = const [], + }); + + /// Constructs an instance of [LinuxPlatformInfoData] from [json]. + factory LinuxNotificationInfo.fromJson(Map json) { + final List? actionsJson = json['actions'] as List?; + final List? actions = actionsJson + // ignore: avoid_annotating_with_dynamic + ?.map((dynamic json) => + LinuxNotificationActionInfo.fromJson(json as Map)) + .toList(); + return LinuxNotificationInfo( + id: json['id'] as int, + systemId: json['systemId'] as int, + payload: json['payload'] as String?, + actions: actions ?? [], + ); + } + + /// Notification id + final int id; + + /// Notification id, which is returned by the system, + /// see Desktop Notifications Specification https://specifications.freedesktop.org/notification-spec/latest/ + final int systemId; + + /// Notification payload, that will be passed back to the app + /// when a notification is tapped on. + final String? payload; + + /// List of actions info + final List actions; + + /// Returns the object as a key-value map + Map toJson() => { + 'id': id, + 'systemId': systemId, + 'payload': payload, + 'actions': + actions.map((LinuxNotificationActionInfo a) => a.toJson()).toList(), + }; + + /// Creates a copy of this object, + /// but with the given fields replaced with the new values. + LinuxNotificationInfo copyWith({ + int? id, + int? systemId, + String? payload, + List? actions, + }) => + LinuxNotificationInfo( + id: id ?? this.id, + systemId: systemId ?? this.systemId, + payload: payload ?? this.payload, + actions: actions ?? this.actions, + ); + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + + return other is LinuxNotificationInfo && + other.id == id && + other.systemId == systemId && + other.payload == payload && + listEquals(other.actions, actions); + } + + @override + int get hashCode => + id.hashCode ^ systemId.hashCode ^ payload.hashCode ^ actions.hashCode; +} + +/// Represents a Linux notification action information +@immutable +class LinuxNotificationActionInfo { + /// Constructs an instance of [LinuxNotificationActionInfo]. + const LinuxNotificationActionInfo({ + required this.key, + }); + + /// Constructs an instance of [LinuxNotificationActionInfo] from [json]. + factory LinuxNotificationActionInfo.fromJson(Map json) => + LinuxNotificationActionInfo(key: json['key'] as String); + + /// Unique action key. + final String key; + + /// Returns the object as a key-value map + Map toJson() => {'key': key}; + + /// Creates a copy of this object, + /// but with the given fields replaced with the new values. + LinuxNotificationActionInfo copyWith({ + String? key, + String? payload, + }) => + LinuxNotificationActionInfo(key: key ?? this.key); + + @override + bool operator ==(Object other) { + if (identical(this, other)) { + return true; + } + + return other is LinuxNotificationActionInfo && other.key == key; + } + + @override + int get hashCode => key.hashCode; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/notifications_manager.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/notifications_manager.dart new file mode 100755 index 00000000..0fe413ce --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/notifications_manager.dart @@ -0,0 +1,398 @@ +import 'dart:async'; + +import 'package:dbus/dbus.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_local_notifications_platform_interface/flutter_local_notifications_platform_interface.dart'; +import 'package:path/path.dart' as path; + +import 'dbus_wrapper.dart'; +import 'helpers.dart'; +import 'model/capabilities.dart'; +import 'model/enums.dart'; +import 'model/hint.dart'; +import 'model/icon.dart'; +import 'model/initialization_settings.dart'; +import 'model/location.dart'; +import 'model/notification_details.dart'; +import 'model/sound.dart'; +import 'model/timeout.dart'; +import 'notification_info.dart'; +import 'platform_info.dart'; +import 'storage.dart'; + +/// Linux notification manager and client +class LinuxNotificationManager { + /// Constructs an instance of of [LinuxNotificationManager] + LinuxNotificationManager() + : _dbus = DBusWrapper(), + _platformInfo = LinuxPlatformInfo(), + _storage = NotificationStorage(); + + /// Constructs an instance of of [LinuxNotificationManager] + /// with the given class dependencies. + @visibleForTesting + LinuxNotificationManager.private({ + DBusWrapper? dbus, + LinuxPlatformInfo? platformInfo, + NotificationStorage? storage, + }) : _dbus = dbus ?? DBusWrapper(), + _platformInfo = platformInfo ?? LinuxPlatformInfo(), + _storage = storage ?? NotificationStorage(); + + final DBusWrapper _dbus; + final LinuxPlatformInfo _platformInfo; + final NotificationStorage _storage; + + late final LinuxInitializationSettings _initializationSettings; + late final DidReceiveNotificationResponseCallback? + _onDidReceiveNotificationResponse; + late final LinuxPlatformInfoData _platformData; + + bool _initialized = false; + + /// Initializes the manager. + /// Call this method on application before using the manager further. + Future initialize( + LinuxInitializationSettings initializationSettings, { + DidReceiveNotificationResponseCallback? onDidReceiveNotificationResponse, + }) async { + if (_initialized) { + return _initialized; + } + _initialized = true; + _initializationSettings = initializationSettings; + _onDidReceiveNotificationResponse = onDidReceiveNotificationResponse; + _dbus.build( + destination: _DBusInterfaceSpec.destination, + path: _DBusInterfaceSpec.path, + ); + _platformData = await _platformInfo.getAll(); + + await _storage.forceReloadCache(); + _subscribeSignals(); + return _initialized; + } + + /// Show notification + Future show( + int id, + String? title, + String? body, { + LinuxNotificationDetails? details, + String? payload, + }) async { + final LinuxNotificationInfo? prevNotify = await _storage.getById(id); + final LinuxNotificationIcon? defaultIcon = + _initializationSettings.defaultIcon; + + final DBusMethodSuccessResponse result = await _dbus.callMethod( + _DBusInterfaceSpec.destination, + _DBusMethodsSpec.notify, + [ + // app_name + DBusString(_platformData.appName ?? ''), + // replaces_id + DBusUint32(prevNotify?.systemId ?? 0), + // app_icon + DBusString(_getAppIcon(details?.icon ?? defaultIcon) ?? ''), + // summary + DBusString(title ?? ''), + // body + DBusString(body ?? ''), + // actions + DBusArray.string(_buildActions(details, _initializationSettings)), + // hints + DBusDict.stringVariant(_buildHints(details, _initializationSettings)), + // expire_timeout + DBusInt32( + details?.timeout.value ?? + const LinuxNotificationTimeout.systemDefault().value, + ), + ], + replySignature: DBusSignature('u'), + ); + final List? actionsInfo = details?.actions + .map( + (LinuxNotificationAction action) => LinuxNotificationActionInfo( + key: action.key, + ), + ) + .toList(); + + final int systemId = (result.returnValues[0] as DBusUint32).value; + final LinuxNotificationInfo notify = prevNotify?.copyWith( + systemId: systemId, + payload: payload, + actions: actionsInfo, + ) ?? + LinuxNotificationInfo( + id: id, + systemId: systemId, + payload: payload, + actions: actionsInfo ?? [], + ); + await _storage.insert(notify); + } + + Map _buildHints( + LinuxNotificationDetails? details, + LinuxInitializationSettings initSettings, + ) { + final Map hints = {}; + final LinuxNotificationIcon? icon = + details?.icon ?? initSettings.defaultIcon; + if (icon?.type == LinuxIconType.byteData) { + final LinuxRawIconData data = icon!.content as LinuxRawIconData; + hints['image-data'] = DBusStruct( + [ + DBusInt32(data.width), + DBusInt32(data.height), + DBusInt32(data.rowStride), + DBusBoolean(data.hasAlpha), + DBusInt32(data.bitsPerSample), + DBusInt32(data.channels), + DBusArray.byte(data.data), + ], + ); + } + final LinuxNotificationSound? sound = + details?.sound ?? initSettings.defaultSound; + if (sound != null) { + switch (sound.type) { + case LinuxSoundType.assets: + hints['sound-file'] = DBusString( + path.join( + _platformData.assetsPath!, + sound.content as String, + ), + ); + break; + case LinuxSoundType.theme: + hints['sound-name'] = DBusString(sound.content as String); + break; + } + } + if (details?.category != null) { + hints['category'] = DBusString(details!.category!.name); + } + if (details?.urgency != null) { + hints['urgency'] = DBusByte(details!.urgency!.index); + } + if (details?.resident ?? false) { + hints['resident'] = const DBusBoolean(true); + } + final bool? suppressSound = + details?.suppressSound ?? initSettings.defaultSuppressSound; + if (suppressSound ?? false) { + hints['suppress-sound'] = const DBusBoolean(true); + } + if (details?.transient ?? false) { + hints['transient'] = const DBusBoolean(true); + } + if (details?.location != null) { + final LinuxNotificationLocation location = details!.location!; + hints['x'] = DBusByte(location.x); + hints['y'] = DBusByte(location.y); + } + if (details?.actionKeyAsIconName ?? false) { + hints['action-icons'] = const DBusBoolean(true); + } + if (details?.customHints != null) { + hints.addAll(_buildCustomHints(details!.customHints!)); + } + + return hints; + } + + Map _buildCustomHints( + List hints, + ) => + Map.fromEntries( + hints.map( + (LinuxNotificationCustomHint hint) => MapEntry( + hint.name, + hint.value.toDBusValue(), + ), + ), + ); + + List _buildActions( + LinuxNotificationDetails? details, + LinuxInitializationSettings initSettings, + ) { + // Add default action, which is triggered when the notification is clicked + final List actions = [ + _kDefaultActionName, + details?.defaultActionName ?? initSettings.defaultActionName, + ]; + if (details != null) { + for (final LinuxNotificationAction action in details.actions) { + actions + ..add(action.key) + ..add(action.label); + } + } + return actions; + } + + /// Cancel notification with the given [id]. + Future cancel(int id) async { + final LinuxNotificationInfo? notify = await _storage.getById(id); + await _storage.removeById(id); + if (notify != null) { + await _dbusCancel(notify.systemId); + } + } + + /// Cancel all notifications. + Future cancelAll() async { + final List notifyList = await _storage.getAll(); + final List idList = []; + for (final LinuxNotificationInfo notify in notifyList) { + idList.add(notify.id); + await _dbusCancel(notify.systemId); + } + await _storage.removeByIdList(idList); + } + + /// Returns the system notification server capabilities. + Future getCapabilities() async { + final DBusMethodSuccessResponse result = await _dbus.callMethod( + _DBusInterfaceSpec.destination, + _DBusMethodsSpec.getCapabilities, + [], + replySignature: DBusSignature('as'), + ); + final Set capsSet = (result.returnValues[0] as DBusArray) + .children + .map((DBusValue c) => (c as DBusString).value) + .toSet(); + + final LinuxServerCapabilities capabilities = LinuxServerCapabilities( + otherCapabilities: const {}, + body: capsSet.remove('body'), + bodyHyperlinks: capsSet.remove('body-hyperlinks'), + bodyImages: capsSet.remove('body-images'), + bodyMarkup: capsSet.remove('body-markup'), + iconMulti: capsSet.remove('icon-multi'), + iconStatic: capsSet.remove('icon-static'), + persistence: capsSet.remove('persistence'), + sound: capsSet.remove('sound'), + actions: capsSet.remove('actions'), + actionIcons: capsSet.remove('action-icons'), + ); + return capabilities.copyWith(otherCapabilities: capsSet); + } + + /// Returns a [Map] with the specified notification id as the key + /// and the id, assigned by the system, as the value. + Future> getSystemIdMap() async => + Map.fromEntries(await _storage.getAll().then( + (List list) => list.map( + (LinuxNotificationInfo notify) => MapEntry( + notify.id, + notify.systemId, + ), + ), + )); + + Future _dbusCancel(int systemId) => _dbus.callMethod( + _DBusInterfaceSpec.destination, + _DBusMethodsSpec.closeNotification, + [DBusUint32(systemId)], + replySignature: DBusSignature(''), + ); + + String? _getAppIcon(LinuxNotificationIcon? icon) { + if (icon == null) { + return null; + } + switch (icon.type) { + case LinuxIconType.assets: + if (_platformData.assetsPath == null) { + return null; + } else { + final String relativePath = icon.content as String; + return path.join(_platformData.assetsPath!, relativePath); + } + case LinuxIconType.byteData: + return null; + case LinuxIconType.theme: + return icon.content as String; + case LinuxIconType.filePath: + return icon.content as String; + } + } + + /// Subscribe to the signals for actions and closing notifications. + void _subscribeSignals() { + _dbus.subscribeSignal(_DBusMethodsSpec.actionInvoked).listen( + (DBusSignal s) async { + if (s.signature != DBusSignature('us')) { + return; + } + + final int systemId = (s.values[0] as DBusUint32).value; + final String actionKey = (s.values[1] as DBusString).value; + final LinuxNotificationInfo? notify = + await _storage.getBySystemId(systemId); + if (notify == null) { + return; + } + if (actionKey == _kDefaultActionName) { + _onDidReceiveNotificationResponse?.call( + NotificationResponse( + id: notify.id, + payload: notify.payload, + notificationResponseType: + NotificationResponseType.selectedNotification, + ), + ); + } else { + final LinuxNotificationActionInfo? actionInfo = + notify.actions.firstWhere( + (LinuxNotificationActionInfo a) => a.key == actionKey, + ); + if (actionInfo == null) { + return; + } + _onDidReceiveNotificationResponse?.call( + NotificationResponse( + id: notify.id, + actionId: actionInfo.key, + payload: notify.payload, + notificationResponseType: + NotificationResponseType.selectedNotificationAction, + ), + ); + } + }, + ); + + _dbus.subscribeSignal(_DBusMethodsSpec.notificationClosed).listen( + (DBusSignal s) async { + if (s.signature != DBusSignature('uu')) { + return; + } + + final int systemId = (s.values[0] as DBusUint32).value; + await _storage.removeBySystemId(systemId); + }, + ); + } +} + +const String _kDefaultActionName = 'default'; + +class _DBusInterfaceSpec { + static const String destination = 'org.freedesktop.Notifications'; + static const String path = '/org/freedesktop/Notifications'; +} + +class _DBusMethodsSpec { + static const String notify = 'Notify'; + static const String closeNotification = 'CloseNotification'; + static const String actionInvoked = 'ActionInvoked'; + static const String notificationClosed = 'NotificationClosed'; + static const String getCapabilities = 'GetCapabilities'; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/platform_info.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/platform_info.dart new file mode 100755 index 00000000..08d6ecfb --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/platform_info.dart @@ -0,0 +1,80 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:path/path.dart' as path; +import 'package:xdg_directories/xdg_directories.dart' as xdg; + +import 'posix.dart'; + +/// Provides Linux platform-specific info +class LinuxPlatformInfo { + final Posix _posix = Posix(); + + /// Returns all platform-specific info + Future getAll() async { + try { + final String exePath = + await File('/proc/self/exe').resolveSymbolicLinks(); + final String processName = path.basenameWithoutExtension(exePath); + final String appPath = path.dirname(exePath); + final String assetPath = path.join(appPath, 'data', 'flutter_assets'); + final String versionPath = path.join(assetPath, 'version.json'); + final Map json = jsonDecode( + await File(versionPath).readAsString(), + ); + late final Directory runtimeDir; + if (xdg.runtimeDir == null) { + final int pid = _posix.getpid(); + final int userId = _posix.getuid(); + final int sessionId = _posix.getsid(pid); + final Map env = Platform.environment; + final String? tmpdir = env['TMPDIR']; + runtimeDir = Directory( + path.join( + tmpdir == null || tmpdir.isEmpty ? '/tmp' : tmpdir, + processName, + '$userId', + '$sessionId', + ), + ); + } else { + runtimeDir = Directory(path.join(xdg.runtimeDir!.path, processName)); + } + if (!runtimeDir.existsSync()) { + await runtimeDir.create(recursive: true); + } + + return LinuxPlatformInfoData( + appName: json['app_name'] ?? '', + assetsPath: assetPath, + runtimePath: runtimeDir.path, + ); + // ignore: avoid_catches_without_on_clauses + } catch (e) { + return const LinuxPlatformInfoData(); + } + } +} + +/// Represents Linux platform-specific info +class LinuxPlatformInfoData { + /// Constructs an instance of [LinuxPlatformInfoData]. + const LinuxPlatformInfoData({ + this.appName, + this.assetsPath, + this.runtimePath, + }); + + /// Application name + final String? appName; + + /// Path to the Flutter Assets directory + final String? assetsPath; + + /// The base directory relative to which user-specific runtime files and + /// other file objects should be placed + /// (Corresponds to `$XDG_RUNTIME_DIR` environment variable). + /// Please see XDG Base Directory Specification https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + /// If `$XDG_RUNTIME_DIR` is not set, the following directory structure is used: `/[$TMPDIR|tmp]/APP_NAME/USER_ID/SESSION_ID` + final String? runtimePath; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/posix.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/posix.dart new file mode 100755 index 00000000..f4cbddef --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/posix.dart @@ -0,0 +1,27 @@ +import 'dart:ffi' as ffi; + +/// Represents Linux POSIX calls. +class Posix { + /// Constructs an instance of [Posix]. + Posix() { + final ffi.DynamicLibrary _dylib = ffi.DynamicLibrary.open('libc.so.6'); + getpid = _dylib + .lookup>('getpid') + .asFunction(); + getsid = _dylib + .lookup>('getsid') + .asFunction(); + getuid = _dylib + .lookup>('getuid') + .asFunction(); + } + + /// Get the process ID of the calling process. + late final int Function() getpid; + + /// Return the session ID of the given process. + late final int Function(int pid) getsid; + + /// Get the real user ID of the calling process. + late final int Function() getuid; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/storage.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/storage.dart new file mode 100755 index 00000000..3bba1ed7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/lib/src/storage.dart @@ -0,0 +1,178 @@ +import 'dart:collection'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:path/path.dart' as path; + +import 'file_system.dart'; +import 'notification_info.dart'; +import 'platform_info.dart'; + +const String _kFileName = 'notification_plugin_cache.json'; + +/// Represents a persisten storage for the notifications info, +/// see [LinuxNotificationInfo]. +/// The storage data exists within the user session. +class NotificationStorage { + /// Constructs an instance of of [NotificationStorageImpl]. + NotificationStorage({ + LinuxPlatformInfo? platformInfo, + FileSystem? fs, + }) : _platformInfo = platformInfo ?? LinuxPlatformInfo(), + _fs = fs ?? LocalFileSystem(); + + final LinuxPlatformInfo _platformInfo; + final FileSystem _fs; + + _Cache? _cachedInfo; + + /// Get all notifications. + Future> getAll() async { + final _Cache cache = await _readInfoMap(); + return cache.toImmutableMap().values.toList(); + } + + /// Get notification by [LinuxNotificationInfo.id]. + Future getBySystemId(int systemId) async { + final _Cache cache = await _readInfoMap(); + return cache.getBySystemId(systemId); + } + + /// Get notification by [LinuxNotificationInfo.systemId]. + Future getById(int id) async { + final _Cache cache = await _readInfoMap(); + return cache.getById(id); + } + + /// Insert notification to the storage. + /// Returns `true` if the operation succeeded. + Future insert(LinuxNotificationInfo notification) async { + final _Cache cache = await _readInfoMap(); + cache.insert(notification); + return _writeInfoList(cache.values.toList()); + } + + /// Remove notification from the storage by [LinuxNotificationInfo.id]. + /// Returns `true` if the operation succeeded. + Future removeById(int id) async { + final _Cache cache = await _readInfoMap(); + cache.removeById(id); + return _writeInfoList(cache.values.toList()); + } + + /// Remove notification from the storage by [LinuxNotificationInfo.systemId]. + /// Returns `true` if the operation succeeded. + Future removeBySystemId(int systemId) async { + final _Cache cache = await _readInfoMap(); + final LinuxNotificationInfo? info = cache.getBySystemId(systemId); + if (info != null) { + cache.removeById(info.id); + } + return _writeInfoList(cache.values.toList()); + } + + /// Remove notification from the storage by [idList]. + /// Returns `true` if the operation succeeded. + Future removeByIdList(List idList) async { + final _Cache cache = await _readInfoMap(); + // ignore: prefer_foreach + for (final int id in idList) { + cache.removeById(id); + } + return _writeInfoList(cache.values.toList()); + } + + /// Force read info from the disk to the cache. + Future forceReloadCache() async { + _cachedInfo = await _readFromCache(); + } + + Future _getStorageFile() async { + final LinuxPlatformInfoData data = await _platformInfo.getAll(); + final String? dir = data.runtimePath; + if (dir == null) { + return null; + } + return _fs.open(path.join(dir, _kFileName)); + } + + /// Gets a [LinuxNotificationInfo] from the stored file. + /// Once read, the data are maintained in memory. + Future<_Cache> _readInfoMap() async { + if (_cachedInfo != null) { + return _cachedInfo!; + } + return _cachedInfo = await _readFromCache(); + } + + Future<_Cache> _readFromCache() async { + final _Cache cache = _Cache(); + final File? storageFile = await _getStorageFile(); + if (storageFile != null && storageFile.existsSync()) { + final String jsonStr = storageFile.readAsStringSync(); + if (jsonStr.isNotEmpty) { + final dynamic json = jsonDecode(jsonStr); + if (json is List) { + for (final dynamic j in json) { + final LinuxNotificationInfo info = + LinuxNotificationInfo.fromJson(j); + cache.insert(info); + } + } else { + cache.insert(LinuxNotificationInfo.fromJson(json)); + } + } + } + return cache; + } + + /// Writes info list to disk. Returns [true] if the operation succeeded. + Future _writeInfoList(List infoList) async { + try { + final File? storageFile = await _getStorageFile(); + if (storageFile == null) { + return false; + } + if (!storageFile.existsSync()) { + storageFile.createSync(recursive: true); + } + final String jsonStr = jsonEncode(infoList); + storageFile.writeAsStringSync(jsonStr); + } on IOException catch (e) { + // ignore: avoid_print + print('Error saving preferences to disk: $e'); + return false; + } + return true; + } +} + +class _Cache { + _Cache() + : _infoMap = {}, + _systemIdMap = {}; + + final Map _infoMap; + + /// System ID to ID map. + final Map _systemIdMap; + + LinuxNotificationInfo? getById(int? id) => _infoMap[id]; + + LinuxNotificationInfo? getBySystemId(int? id) => _infoMap[_systemIdMap[id]]; + + void insert(LinuxNotificationInfo info) { + _infoMap[info.id] = info; + _systemIdMap[info.systemId] = info.id; + } + + void removeById(int id) { + final LinuxNotificationInfo? info = _infoMap.remove(id); + _systemIdMap.remove(info?.systemId); + } + + Iterable get values => _infoMap.values; + + Map toImmutableMap() => + UnmodifiableMapView(_infoMap); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/pubspec.yaml new file mode 100755 index 00000000..1c0b4f1c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/pubspec.yaml @@ -0,0 +1,32 @@ +name: flutter_local_notifications_linux +description: Linux implementation of the flutter_local_notifications plugin +version: 6.0.0 +homepage: https://github.com/MaikuB/flutter_local_notifications/tree/master/flutter_local_notifications +issue_tracker: https://github.com/MaikuB/flutter_local_notifications/issues + +flutter: + plugin: + implements: flutter_local_notifications + platforms: + linux: + dartPluginClass: LinuxFlutterLocalNotificationsPlugin + + +dependencies: + dbus: ^0.7.8 + ffi: ^2.0.1 + flutter: + sdk: flutter + flutter_local_notifications_platform_interface: ^9.0.0 + path: ^1.8.0 + xdg_directories: ">=0.2.0+1 <2.0.0" + +dev_dependencies: + build_runner: ^2.3.3 + flutter_test: + sdk: flutter + mockito: ^5.3.2 + +environment: + sdk: ^3.4.0 + flutter: ">=3.22.0" diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/notifications_manager_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/notifications_manager_test.dart new file mode 100755 index 00000000..4e89c062 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/notifications_manager_test.dart @@ -0,0 +1,1456 @@ +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:dbus/dbus.dart'; +import 'package:flutter_local_notifications_linux/flutter_local_notifications_linux.dart'; +import 'package:flutter_local_notifications_linux/src/dbus_wrapper.dart'; +import 'package:flutter_local_notifications_linux/src/model/hint.dart'; +import 'package:flutter_local_notifications_linux/src/notification_info.dart'; +import 'package:flutter_local_notifications_linux/src/notifications_manager.dart'; +import 'package:flutter_local_notifications_linux/src/platform_info.dart'; +import 'package:flutter_local_notifications_linux/src/storage.dart'; +import 'package:flutter_local_notifications_platform_interface/flutter_local_notifications_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:path/path.dart' as path; + +@GenerateNiceMocks(>[ + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), + MockSpec(), +]) +import 'notifications_manager_test.mocks.dart'; + +class FakeStreamSubscription extends Fake implements StreamSubscription {} + +// ignore: one_member_abstracts +abstract class DidReceiveNotificationResponseCallback { + Future call(NotificationResponse notificationResponse); +} + +/*class MockDidReceiveNotificationResponseCallback extends Mock + implements _DidReceiveNotificationResponseCallback {}*/ + +void main() { + group('Notifications manager |', () { + late LinuxNotificationManager manager; + late final MockDBusWrapper mockDbus; + late final MockDBusRemoteObjectSignalStream mockActionInvokedSignal; + late final MockDBusRemoteObjectSignalStream mockNotifyClosedSignal; + late final MockLinuxPlatformInfo mockPlatformInfo; + late final MockNotificationStorage mockStorage; + late final MockDidReceiveNotificationResponseCallback + mockDidReceiveNotificationResponseCallback; + + const LinuxPlatformInfoData platformInfo = LinuxPlatformInfoData( + appName: 'Test', + assetsPath: 'assets', + runtimePath: 'run', + ); + + setUpAll(() { + mockDbus = MockDBusWrapper(); + mockActionInvokedSignal = MockDBusRemoteObjectSignalStream(); + mockNotifyClosedSignal = MockDBusRemoteObjectSignalStream(); + mockPlatformInfo = MockLinuxPlatformInfo(); + mockStorage = MockNotificationStorage(); + mockDidReceiveNotificationResponseCallback = + MockDidReceiveNotificationResponseCallback(); + + when( + mockPlatformInfo.getAll(), + ).thenAnswer((_) async => platformInfo); + when( + mockStorage.forceReloadCache(), + ).thenAnswer((_) async {}); + when( + mockDbus.build( + destination: 'org.freedesktop.Notifications', + path: '/org/freedesktop/Notifications', + ), + ).thenAnswer((_) {}); + when( + mockDbus.subscribeSignal('ActionInvoked'), + ).thenAnswer((_) => mockActionInvokedSignal); + when( + mockDbus.subscribeSignal('NotificationClosed'), + ).thenAnswer((_) => mockNotifyClosedSignal); + when( + mockDidReceiveNotificationResponseCallback.call(any), + ).thenAnswer((_) async => {}); + }); + + setUp(() { + manager = LinuxNotificationManager.private( + dbus: mockDbus, + platformInfo: mockPlatformInfo, + storage: mockStorage, + ); + + when( + mockActionInvokedSignal.listen(any), + ).thenReturn(FakeStreamSubscription()); + when( + mockNotifyClosedSignal.listen(any), + ).thenReturn(FakeStreamSubscription()); + }); + + void mockCloseMethod() => when( + mockDbus.callMethod( + 'org.freedesktop.Notifications', + 'CloseNotification', + any, + replySignature: DBusSignature(''), + ), + ).thenAnswer( + (_) async => DBusMethodSuccessResponse(), + ); + + VerificationResult verifyCloseMethod(int systemId) => verify( + mockDbus.callMethod( + 'org.freedesktop.Notifications', + 'CloseNotification', + [DBusUint32(systemId)], + replySignature: DBusSignature(''), + ), + ); + + test('Initialize', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: 'test', + ); + + await manager.initialize(initSettings); + + verify(mockPlatformInfo.getAll()).called(1); + verify(mockStorage.forceReloadCache()).called(1); + verify( + mockDbus.build( + destination: 'org.freedesktop.Notifications', + path: '/org/freedesktop/Notifications', + ), + ).called(1); + verify(mockActionInvokedSignal.listen(any)).called(1); + verify(mockNotifyClosedSignal.listen(any)).called(1); + }); + + const String kDefaultActionName = 'Open notification'; + + group('Show |', () { + List buildNotifyMethodValues({ + int? replacesId, + String? appIcon, + String? title, + String? body, + List? actions, + Map? hints, + int? expireTimeout, + }) => + [ + // app_name + DBusString(platformInfo.appName!), + // replaces_id + DBusUint32(replacesId ?? 0), + // app_icon + DBusString(appIcon ?? ''), + // summary + DBusString(title ?? ''), + // body + DBusString(body ?? ''), + // actions + DBusArray.string( + ['default', kDefaultActionName, ...?actions]), + // hints + DBusDict.stringVariant(hints ?? {}), + // expire_timeout + DBusInt32( + expireTimeout ?? + const LinuxNotificationTimeout.systemDefault().value, + ), + ]; + + void mockNotifyMethod(int systemId) => when( + mockDbus.callMethod( + 'org.freedesktop.Notifications', + 'Notify', + any, + replySignature: DBusSignature('u'), + ), + ).thenAnswer( + (_) async => DBusMethodSuccessResponse( + [DBusUint32(systemId)], + ), + ); + + VerificationResult verifyNotifyMethod(List values) => + verify(mockDbus.callMethod( + 'org.freedesktop.Notifications', + 'Notify', + values, + replySignature: DBusSignature('u'), + )); + + test('Simple notification', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final List values = buildNotifyMethodValues( + title: 'Title', + body: 'Body', + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, 'Title', 'Body'); + + verifyNotifyMethod(values).called(1); + verify( + mockStorage.insert(notify), + ).called(1); + }); + + test('Simple notification without title and body', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final List values = buildNotifyMethodValues(); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null); + + verifyNotifyMethod(values).called(1); + verify( + mockStorage.insert(notify), + ).called(1); + }); + + test('Replace previous notification', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo prevNotify = LinuxNotificationInfo( + id: 0, + systemId: 1, + payload: 'payload', + ); + const LinuxNotificationInfo newNotify = LinuxNotificationInfo( + id: 0, + systemId: 2, + payload: 'payload', + ); + + final List values = buildNotifyMethodValues( + replacesId: prevNotify.systemId, + title: 'Title', + body: 'Body', + ); + + mockNotifyMethod(newNotify.systemId); + when( + mockStorage.getById(newNotify.id), + ).thenAnswer((_) async => prevNotify); + when( + mockStorage.insert(newNotify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(newNotify.id, 'Title', 'Body'); + + verifyNotifyMethod(values).called(1); + verify( + mockStorage.insert(newNotify), + ).called(1); + }); + + test('Assets details icon', () async { + final LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultIcon: AssetsLinuxIcon('icon.png'), + ); + + final LinuxNotificationDetails details = LinuxNotificationDetails( + icon: AssetsLinuxIcon('details_icon.png'), + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final List values = buildNotifyMethodValues( + appIcon: path.join(platformInfo.assetsPath!, 'details_icon.png'), + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Byte details icon', () async { + final LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultIcon: AssetsLinuxIcon('icon.png'), + ); + + final ByteDataLinuxIcon icon = ByteDataLinuxIcon( + LinuxRawIconData( + data: Uint8List(64), + width: 8, + height: 8, + ), + ); + final LinuxNotificationDetails details = LinuxNotificationDetails( + icon: icon, + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final List values = buildNotifyMethodValues( + hints: { + 'image-data': DBusStruct( + [ + DBusInt32(icon.iconData.width), + DBusInt32(icon.iconData.height), + DBusInt32(icon.iconData.rowStride), + DBusBoolean(icon.iconData.hasAlpha), + DBusInt32(icon.iconData.bitsPerSample), + DBusInt32(icon.iconData.channels), + DBusArray.byte(icon.iconData.data), + ], + ), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Theme details icon', () async { + final LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultIcon: AssetsLinuxIcon('icon.png'), + ); + + final LinuxNotificationDetails details = LinuxNotificationDetails( + icon: ThemeLinuxIcon('test'), + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final List values = buildNotifyMethodValues( + appIcon: details.icon!.content as String, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Default icon', () async { + final LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultIcon: AssetsLinuxIcon('icon.png'), + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final List values = buildNotifyMethodValues( + appIcon: path.join(platformInfo.assetsPath!, 'icon.png'), + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null); + + verifyNotifyMethod(values).called(1); + }); + + test('Timeout', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + const LinuxNotificationDetails details = LinuxNotificationDetails( + timeout: LinuxNotificationTimeout(100), + ); + + final List values = buildNotifyMethodValues( + expireTimeout: details.timeout.value, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Assets sound in details', () async { + final LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultSound: AssetsLinuxSound('default_sound.mp3'), + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final LinuxNotificationDetails details = LinuxNotificationDetails( + sound: AssetsLinuxSound('sound.mp3'), + ); + + final List values = buildNotifyMethodValues( + hints: { + 'sound-file': DBusString( + path.join( + platformInfo.assetsPath!, + details.sound!.content as String, + ), + ), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Theme sound in details', () async { + final LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultSound: AssetsLinuxSound('default_sound.mp3'), + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final LinuxNotificationDetails details = LinuxNotificationDetails( + sound: ThemeLinuxSound('test'), + ); + + final List values = buildNotifyMethodValues( + hints: { + 'sound-name': DBusString(details.sound!.content as String), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Default sound', () async { + final LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultSound: AssetsLinuxSound('sound.mp3'), + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final List values = buildNotifyMethodValues( + hints: { + 'sound-file': DBusString( + path.join( + platformInfo.assetsPath!, + initSettings.defaultSound!.content as String, + ), + ), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null); + + verifyNotifyMethod(values).called(1); + }); + + test('Category', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + const LinuxNotificationDetails details = LinuxNotificationDetails( + category: LinuxNotificationCategory.email, + ); + + final List values = buildNotifyMethodValues( + hints: { + 'category': DBusString(details.category!.name), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Urgency', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + const LinuxNotificationDetails details = LinuxNotificationDetails( + urgency: LinuxNotificationUrgency.normal, + ); + + final List values = buildNotifyMethodValues( + hints: { + 'urgency': DBusByte(details.urgency!.index), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Resident notification', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + const LinuxNotificationDetails details = LinuxNotificationDetails( + resident: true, + ); + + final List values = buildNotifyMethodValues( + hints: { + 'resident': DBusBoolean(details.resident), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Suppress sound in details', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + const LinuxNotificationDetails details = LinuxNotificationDetails( + suppressSound: true, + ); + + final List values = buildNotifyMethodValues( + hints: { + 'suppress-sound': DBusBoolean(details.suppressSound), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Default suppress sound', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultSuppressSound: true, + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final List values = buildNotifyMethodValues( + hints: { + 'suppress-sound': DBusBoolean(initSettings.defaultSuppressSound), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null); + + verifyNotifyMethod(values).called(1); + }); + + test('Transient notification', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + const LinuxNotificationDetails details = LinuxNotificationDetails( + transient: true, + ); + + final List values = buildNotifyMethodValues( + hints: { + 'transient': DBusBoolean(details.transient), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Notification location', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + const LinuxNotificationDetails details = LinuxNotificationDetails( + location: LinuxNotificationLocation(50, 100), + ); + + final List values = buildNotifyMethodValues( + hints: { + 'x': DBusByte(details.location!.x), + 'y': DBusByte(details.location!.y), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Custom hints', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final LinuxNotificationDetails details = LinuxNotificationDetails( + customHints: [ + LinuxNotificationCustomHint( + 'array-hint', + LinuxHintArrayValue( + [ + LinuxHintStringValue('1'), + LinuxHintStringValue('2'), + ], + ), + ), + LinuxNotificationCustomHint( + 'bool-hint', + LinuxHintBoolValue(true), + ), + LinuxNotificationCustomHint( + 'byte-hint', + LinuxHintByteValue(1), + ), + LinuxNotificationCustomHint( + 'dict-hint', + LinuxHintDictValue( + { + LinuxHintByteValue(1): LinuxHintStringValue('1'), + LinuxHintByteValue(2): LinuxHintStringValue('2'), + }, + ), + ), + LinuxNotificationCustomHint( + 'double-hint', + LinuxHintDoubleValue(1.1), + ), + LinuxNotificationCustomHint( + 'int16-hint', + LinuxHintInt16Value(1), + ), + LinuxNotificationCustomHint( + 'int32-hint', + LinuxHintInt32Value(1), + ), + LinuxNotificationCustomHint( + 'int64-hint', + LinuxHintInt64Value(1), + ), + LinuxNotificationCustomHint( + 'string-hint', + LinuxHintStringValue('test'), + ), + LinuxNotificationCustomHint( + 'struct-hint', + LinuxHintStructValue( + [ + LinuxHintStringValue('test'), + LinuxHintBoolValue(true), + ], + ), + ), + LinuxNotificationCustomHint( + 'uint16-hint', + LinuxHintUint16Value(1), + ), + LinuxNotificationCustomHint( + 'uint32-hint', + LinuxHintUint32Value(1), + ), + LinuxNotificationCustomHint( + 'uint64-hint', + LinuxHintUint64Value(1), + ), + LinuxNotificationCustomHint( + 'variant-hint', + LinuxHintVariantValue(LinuxHintByteValue(1)), + ), + ], + ); + + final List values = buildNotifyMethodValues( + hints: { + 'array-hint': DBusArray( + DBusSignature('s'), + [ + const DBusString('1'), + const DBusString('2'), + ], + ), + 'bool-hint': const DBusBoolean(true), + 'byte-hint': const DBusByte(1), + 'dict-hint': DBusDict( + DBusSignature('y'), + DBusSignature('s'), + { + const DBusByte(1): const DBusString('1'), + const DBusByte(2): const DBusString('2'), + }, + ), + 'double-hint': const DBusDouble(1.1), + 'int16-hint': const DBusInt16(1), + 'int32-hint': const DBusInt32(1), + 'int64-hint': const DBusInt64(1), + 'string-hint': const DBusString('test'), + 'struct-hint': DBusStruct( + [ + const DBusString('test'), + const DBusBoolean(true), + ], + ), + 'uint16-hint': const DBusUint16(1), + 'uint32-hint': const DBusUint32(1), + 'uint64-hint': const DBusUint64(1), + 'variant-hint': const DBusVariant(DBusByte(1)), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('File path details icon', () async { + final LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultIcon: FilePathLinuxIcon('/foo/bar/icon.png'), + ); + + final LinuxNotificationDetails details = LinuxNotificationDetails( + icon: FilePathLinuxIcon('/foo/bar/icon.png'), + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + final List values = + buildNotifyMethodValues(appIcon: '/foo/bar/icon.png'); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Notification actions', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + actions: [ + LinuxNotificationActionInfo(key: '1'), + LinuxNotificationActionInfo(key: '2'), + ], + ); + + const LinuxNotificationDetails details = LinuxNotificationDetails( + actions: [ + LinuxNotificationAction( + key: '1', + label: 'action1', + ), + LinuxNotificationAction( + key: '2', + label: 'action2', + ), + ], + ); + + final List values = buildNotifyMethodValues( + actions: [ + '1', + 'action1', + '2', + 'action2', + ], + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + + test('Notification action key as icon', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + actions: [ + LinuxNotificationActionInfo(key: 'media-eject'), + ], + ); + + const LinuxNotificationDetails details = LinuxNotificationDetails( + actions: [ + LinuxNotificationAction( + key: 'media-eject', + label: 'eject', + ), + ], + actionKeyAsIconName: true, + ); + + final List values = buildNotifyMethodValues( + actions: [ + 'media-eject', + 'eject', + ], + hints: { + 'action-icons': const DBusBoolean(true), + }, + ); + + mockNotifyMethod(notify.systemId); + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => null); + when( + mockStorage.insert(notify), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.show(notify.id, null, null, details: details); + + verifyNotifyMethod(values).called(1); + }); + }); + + test('Cancel', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + defaultSuppressSound: true, + ); + + const LinuxNotificationInfo notify = LinuxNotificationInfo( + id: 0, + systemId: 1, + ); + + mockCloseMethod(); + + when( + mockStorage.getById(notify.id), + ).thenAnswer((_) async => notify); + when( + mockStorage.removeById(notify.id), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.cancel(notify.id); + + verifyCloseMethod(notify.systemId).called(1); + verify( + mockStorage.removeById(notify.id), + ).called(1); + }); + + test('Cancel all', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + ); + + const List notifications = [ + LinuxNotificationInfo( + id: 0, + systemId: 1, + ), + LinuxNotificationInfo( + id: 1, + systemId: 2, + ), + ]; + + mockCloseMethod(); + + when( + mockStorage.getAll(), + ).thenAnswer((_) async => notifications); + when( + mockStorage.removeByIdList( + notifications.map((LinuxNotificationInfo n) => n.id).toList(), + ), + ).thenAnswer((_) async => true); + + await manager.initialize(initSettings); + await manager.cancelAll(); + + for (final LinuxNotificationInfo notify in notifications) { + verifyCloseMethod(notify.systemId).called(1); + } + verify( + mockStorage.removeByIdList( + notifications.map((LinuxNotificationInfo n) => n.id).toList(), + ), + ).called(1); + }); + + test('Notification closed by system', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + ); + + const List notifications = [ + LinuxNotificationInfo( + id: 0, + systemId: 1, + ), + LinuxNotificationInfo( + id: 1, + systemId: 2, + ), + ]; + + final List> completers = >[]; + for (final LinuxNotificationInfo notify in notifications) { + when( + mockStorage.removeBySystemId(notify.systemId), + ).thenAnswer((_) async => true); + } + + when( + mockNotifyClosedSignal.listen(any), + ).thenAnswer((Invocation invocation) { + final Future Function(DBusSignal) callback = + invocation.positionalArguments.single; + for (final LinuxNotificationInfo notify in notifications) { + callback( + DBusSignal( + sender: '', + path: DBusObjectPath('/org/freedesktop/Notifications'), + interface: 'org.freedesktop.Notifications', + name: 'NotificationClosed', + values: [ + DBusUint32(notify.systemId), + const DBusUint32(1), + ], + ), + ).then((_) { + for (final Completer completer in completers) { + if (!completer.isCompleted) { + completer.complete(); + } + } + }); + } + return FakeStreamSubscription(); + }); + + await manager.initialize(initSettings); + await Future.forEach( + completers, + (Completer completer) => completer.future, + ); + + for (final LinuxNotificationInfo notify in notifications) { + verify( + mockStorage.removeBySystemId(notify.systemId), + ).called(1); + } + }); + + test('Open notification', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + ); + + const List notifications = [ + LinuxNotificationInfo( + id: 0, + systemId: 1, + payload: 'payload1', + ), + LinuxNotificationInfo( + id: 1, + systemId: 2, + payload: 'payload2', + ), + ]; + + final List> completers = >[]; + for (final LinuxNotificationInfo notify in notifications) { + when( + mockStorage.getBySystemId(notify.systemId), + ).thenAnswer((_) async => notify); + completers.add(Completer()); + } + when( + mockActionInvokedSignal.listen(any), + ).thenAnswer((Invocation invocation) { + final Future Function(DBusSignal) callback = + invocation.positionalArguments.single; + for (final LinuxNotificationInfo notify in notifications) { + callback( + DBusSignal( + sender: '', + path: DBusObjectPath('/org/freedesktop/Notifications'), + interface: 'org.freedesktop.Notifications', + name: 'ActionInvoked', + values: [ + DBusUint32(notify.systemId), + const DBusString('default'), + ], + ), + ).then((_) { + for (final Completer completer in completers) { + if (!completer.isCompleted) { + completer.complete(); + } + } + }); + } + return FakeStreamSubscription(); + }); + + await manager.initialize( + initSettings, + onDidReceiveNotificationResponse: + mockDidReceiveNotificationResponseCallback, + ); + await Future.forEach( + completers, + (Completer completer) => completer.future, + ); + + for (final LinuxNotificationInfo notify in notifications) { + verify( + mockStorage.getBySystemId(notify.systemId), + ).called(1); + } + }); + + test('Notification server capabilities', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings(defaultActionName: kDefaultActionName); + + when( + mockDbus.callMethod( + 'org.freedesktop.Notifications', + 'GetCapabilities', + [], + replySignature: DBusSignature('as'), + ), + ).thenAnswer( + (_) async => DBusMethodSuccessResponse( + [ + DBusArray( + DBusSignature('s'), + [ + const DBusString('body'), + const DBusString('body-hyperlinks'), + const DBusString('body-images'), + const DBusString('body-markup'), + const DBusString('icon-multi'), + const DBusString('icon-static'), + const DBusString('persistence'), + const DBusString('sound'), + const DBusString('test-cap'), + const DBusString('actions'), + const DBusString('action-icons'), + ], + ), + ], + ), + ); + + await manager.initialize(initSettings); + expect( + await manager.getCapabilities(), + const LinuxServerCapabilities( + otherCapabilities: {'test-cap'}, + body: true, + bodyHyperlinks: true, + bodyImages: true, + bodyMarkup: true, + iconMulti: true, + iconStatic: true, + persistence: true, + sound: true, + actions: true, + actionIcons: true, + ), + ); + }); + + test('Get system ID map', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + ); + + const List notifications = [ + LinuxNotificationInfo( + id: 0, + systemId: 1, + ), + LinuxNotificationInfo( + id: 1, + systemId: 2, + ), + ]; + + when( + mockStorage.getAll(), + ).thenAnswer((_) async => notifications); + + await manager.initialize(initSettings); + expect( + await manager.getSystemIdMap(), + Map.fromEntries( + notifications.map( + (LinuxNotificationInfo notify) => MapEntry( + notify.id, + notify.systemId, + ), + ), + ), + ); + }); + + test('Open notification action', () async { + const LinuxInitializationSettings initSettings = + LinuxInitializationSettings( + defaultActionName: kDefaultActionName, + ); + + const List notifications = [ + LinuxNotificationInfo( + id: 0, + systemId: 1, + actions: [ + LinuxNotificationActionInfo(key: '1'), + ], + ), + LinuxNotificationInfo( + id: 1, + systemId: 2, + actions: [ + LinuxNotificationActionInfo(key: '2'), + ], + ), + ]; + + final List> completers = >[]; + for (final LinuxNotificationInfo notify in notifications) { + when( + mockStorage.getBySystemId(notify.systemId), + ).thenAnswer((_) async => notify); + completers.add(Completer()); + } + when( + mockActionInvokedSignal.listen(any), + ).thenAnswer((Invocation invocation) { + final Future Function(DBusSignal) callback = + invocation.positionalArguments.single; + for (final LinuxNotificationInfo notify in notifications) { + callback( + DBusSignal( + sender: '', + path: DBusObjectPath('/org/freedesktop/Notifications'), + interface: 'org.freedesktop.Notifications', + name: 'ActionInvoked', + values: [ + DBusUint32(notify.systemId), + DBusString(notify.actions[0].key), + ], + ), + ).then((_) { + for (final Completer completer in completers) { + if (!completer.isCompleted) { + completer.complete(); + } + } + }); + } + return FakeStreamSubscription(); + }); + + await manager.initialize( + initSettings, + onDidReceiveNotificationResponse: + mockDidReceiveNotificationResponseCallback, + ); + await Future.forEach( + completers, + (Completer completer) => completer.future, + ); + + for (final LinuxNotificationInfo notify in notifications) { + verify( + mockStorage.getBySystemId(notify.systemId), + ).called(1); + } + }); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/notifications_manager_test.mocks.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/notifications_manager_test.mocks.dart new file mode 100755 index 00000000..a038b2b2 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/notifications_manager_test.mocks.dart @@ -0,0 +1,882 @@ +// Mocks generated by Mockito 5.4.0 from annotations +// in flutter_local_notifications_linux/test/notifications_manager_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:dbus/dbus.dart' as _i2; +import 'package:flutter_local_notifications_linux/src/dbus_wrapper.dart' as _i5; +import 'package:flutter_local_notifications_linux/src/notification_info.dart' + as _i7; +import 'package:flutter_local_notifications_linux/src/platform_info.dart' + as _i4; +import 'package:flutter_local_notifications_linux/src/storage.dart' as _i6; +import 'package:flutter_local_notifications_platform_interface/flutter_local_notifications_platform_interface.dart' + as _i9; +import 'package:mockito/mockito.dart' as _i1; + +import 'notifications_manager_test.dart' as _i8; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeDBusMethodSuccessResponse_0 extends _i1.SmartFake + implements _i2.DBusMethodSuccessResponse { + _FakeDBusMethodSuccessResponse_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDBusRemoteObjectSignalStream_1 extends _i1.SmartFake + implements _i2.DBusRemoteObjectSignalStream { + _FakeDBusRemoteObjectSignalStream_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDBusSignal_2 extends _i1.SmartFake implements _i2.DBusSignal { + _FakeDBusSignal_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeStreamSubscription_3 extends _i1.SmartFake + implements _i3.StreamSubscription { + _FakeStreamSubscription_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFuture_4 extends _i1.SmartFake implements _i3.Future { + _FakeFuture_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeLinuxPlatformInfoData_5 extends _i1.SmartFake + implements _i4.LinuxPlatformInfoData { + _FakeLinuxPlatformInfoData_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [DBusWrapper]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDBusWrapper extends _i1.Mock implements _i5.DBusWrapper { + @override + void build({ + required String? destination, + required String? path, + }) => + super.noSuchMethod( + Invocation.method( + #build, + [], + { + #destination: destination, + #path: path, + }, + ), + returnValueForMissingStub: null, + ); + @override + _i3.Future<_i2.DBusMethodSuccessResponse> callMethod( + String? interface, + String? name, + Iterable<_i2.DBusValue>? values, { + _i2.DBusSignature? replySignature, + bool? noReplyExpected = false, + bool? noAutoStart = false, + bool? allowInteractiveAuthorization = false, + }) => + (super.noSuchMethod( + Invocation.method( + #callMethod, + [ + interface, + name, + values, + ], + { + #replySignature: replySignature, + #noReplyExpected: noReplyExpected, + #noAutoStart: noAutoStart, + #allowInteractiveAuthorization: allowInteractiveAuthorization, + }, + ), + returnValue: _i3.Future<_i2.DBusMethodSuccessResponse>.value( + _FakeDBusMethodSuccessResponse_0( + this, + Invocation.method( + #callMethod, + [ + interface, + name, + values, + ], + { + #replySignature: replySignature, + #noReplyExpected: noReplyExpected, + #noAutoStart: noAutoStart, + #allowInteractiveAuthorization: allowInteractiveAuthorization, + }, + ), + )), + returnValueForMissingStub: + _i3.Future<_i2.DBusMethodSuccessResponse>.value( + _FakeDBusMethodSuccessResponse_0( + this, + Invocation.method( + #callMethod, + [ + interface, + name, + values, + ], + { + #replySignature: replySignature, + #noReplyExpected: noReplyExpected, + #noAutoStart: noAutoStart, + #allowInteractiveAuthorization: allowInteractiveAuthorization, + }, + ), + )), + ) as _i3.Future<_i2.DBusMethodSuccessResponse>); + @override + _i2.DBusRemoteObjectSignalStream subscribeSignal(String? name) => + (super.noSuchMethod( + Invocation.method( + #subscribeSignal, + [name], + ), + returnValue: _FakeDBusRemoteObjectSignalStream_1( + this, + Invocation.method( + #subscribeSignal, + [name], + ), + ), + returnValueForMissingStub: _FakeDBusRemoteObjectSignalStream_1( + this, + Invocation.method( + #subscribeSignal, + [name], + ), + ), + ) as _i2.DBusRemoteObjectSignalStream); +} + +/// A class which mocks [DBusRemoteObjectSignalStream]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDBusRemoteObjectSignalStream extends _i1.Mock + implements _i2.DBusRemoteObjectSignalStream { + @override + bool get isBroadcast => (super.noSuchMethod( + Invocation.getter(#isBroadcast), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + @override + _i3.Future get length => (super.noSuchMethod( + Invocation.getter(#length), + returnValue: _i3.Future.value(0), + returnValueForMissingStub: _i3.Future.value(0), + ) as _i3.Future); + @override + _i3.Future get isEmpty => (super.noSuchMethod( + Invocation.getter(#isEmpty), + returnValue: _i3.Future.value(false), + returnValueForMissingStub: _i3.Future.value(false), + ) as _i3.Future); + @override + _i3.Future<_i2.DBusSignal> get first => (super.noSuchMethod( + Invocation.getter(#first), + returnValue: _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.getter(#first), + )), + returnValueForMissingStub: + _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.getter(#first), + )), + ) as _i3.Future<_i2.DBusSignal>); + @override + _i3.Future<_i2.DBusSignal> get last => (super.noSuchMethod( + Invocation.getter(#last), + returnValue: _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.getter(#last), + )), + returnValueForMissingStub: + _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.getter(#last), + )), + ) as _i3.Future<_i2.DBusSignal>); + @override + _i3.Future<_i2.DBusSignal> get single => (super.noSuchMethod( + Invocation.getter(#single), + returnValue: _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.getter(#single), + )), + returnValueForMissingStub: + _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.getter(#single), + )), + ) as _i3.Future<_i2.DBusSignal>); + @override + _i3.StreamSubscription<_i2.DBusSignal> listen( + void Function(_i2.DBusSignal)? onData, { + Function? onError, + void Function()? onDone, + bool? cancelOnError, + }) => + (super.noSuchMethod( + Invocation.method( + #listen, + [onData], + { + #onError: onError, + #onDone: onDone, + #cancelOnError: cancelOnError, + }, + ), + returnValue: _FakeStreamSubscription_3<_i2.DBusSignal>( + this, + Invocation.method( + #listen, + [onData], + { + #onError: onError, + #onDone: onDone, + #cancelOnError: cancelOnError, + }, + ), + ), + returnValueForMissingStub: _FakeStreamSubscription_3<_i2.DBusSignal>( + this, + Invocation.method( + #listen, + [onData], + { + #onError: onError, + #onDone: onDone, + #cancelOnError: cancelOnError, + }, + ), + ), + ) as _i3.StreamSubscription<_i2.DBusSignal>); + @override + _i3.Stream<_i2.DBusSignal> asBroadcastStream({ + void Function(_i3.StreamSubscription<_i2.DBusSignal>)? onListen, + void Function(_i3.StreamSubscription<_i2.DBusSignal>)? onCancel, + }) => + (super.noSuchMethod( + Invocation.method( + #asBroadcastStream, + [], + { + #onListen: onListen, + #onCancel: onCancel, + }, + ), + returnValue: _i3.Stream<_i2.DBusSignal>.empty(), + returnValueForMissingStub: _i3.Stream<_i2.DBusSignal>.empty(), + ) as _i3.Stream<_i2.DBusSignal>); + @override + _i3.Stream<_i2.DBusSignal> where(bool Function(_i2.DBusSignal)? test) => + (super.noSuchMethod( + Invocation.method( + #where, + [test], + ), + returnValue: _i3.Stream<_i2.DBusSignal>.empty(), + returnValueForMissingStub: _i3.Stream<_i2.DBusSignal>.empty(), + ) as _i3.Stream<_i2.DBusSignal>); + @override + _i3.Stream map(S Function(_i2.DBusSignal)? convert) => + (super.noSuchMethod( + Invocation.method( + #map, + [convert], + ), + returnValue: _i3.Stream.empty(), + returnValueForMissingStub: _i3.Stream.empty(), + ) as _i3.Stream); + @override + _i3.Stream asyncMap( + _i3.FutureOr Function(_i2.DBusSignal)? convert) => + (super.noSuchMethod( + Invocation.method( + #asyncMap, + [convert], + ), + returnValue: _i3.Stream.empty(), + returnValueForMissingStub: _i3.Stream.empty(), + ) as _i3.Stream); + @override + _i3.Stream asyncExpand( + _i3.Stream? Function(_i2.DBusSignal)? convert) => + (super.noSuchMethod( + Invocation.method( + #asyncExpand, + [convert], + ), + returnValue: _i3.Stream.empty(), + returnValueForMissingStub: _i3.Stream.empty(), + ) as _i3.Stream); + @override + _i3.Stream<_i2.DBusSignal> handleError( + Function? onError, { + bool Function(dynamic)? test, + }) => + (super.noSuchMethod( + Invocation.method( + #handleError, + [onError], + {#test: test}, + ), + returnValue: _i3.Stream<_i2.DBusSignal>.empty(), + returnValueForMissingStub: _i3.Stream<_i2.DBusSignal>.empty(), + ) as _i3.Stream<_i2.DBusSignal>); + @override + _i3.Stream expand(Iterable Function(_i2.DBusSignal)? convert) => + (super.noSuchMethod( + Invocation.method( + #expand, + [convert], + ), + returnValue: _i3.Stream.empty(), + returnValueForMissingStub: _i3.Stream.empty(), + ) as _i3.Stream); + @override + _i3.Future pipe( + _i3.StreamConsumer<_i2.DBusSignal>? streamConsumer) => + (super.noSuchMethod( + Invocation.method( + #pipe, + [streamConsumer], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + @override + _i3.Stream transform( + _i3.StreamTransformer<_i2.DBusSignal, S>? streamTransformer) => + (super.noSuchMethod( + Invocation.method( + #transform, + [streamTransformer], + ), + returnValue: _i3.Stream.empty(), + returnValueForMissingStub: _i3.Stream.empty(), + ) as _i3.Stream); + @override + _i3.Future<_i2.DBusSignal> reduce( + _i2.DBusSignal Function( + _i2.DBusSignal, + _i2.DBusSignal, + )? combine) => + (super.noSuchMethod( + Invocation.method( + #reduce, + [combine], + ), + returnValue: _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #reduce, + [combine], + ), + )), + returnValueForMissingStub: + _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #reduce, + [combine], + ), + )), + ) as _i3.Future<_i2.DBusSignal>); + @override + _i3.Future fold( + S? initialValue, + S Function( + S, + _i2.DBusSignal, + )? combine, + ) => + (super.noSuchMethod( + Invocation.method( + #fold, + [ + initialValue, + combine, + ], + ), + returnValue: _FakeFuture_4( + this, + Invocation.method( + #fold, + [ + initialValue, + combine, + ], + ), + ), + returnValueForMissingStub: _FakeFuture_4( + this, + Invocation.method( + #fold, + [ + initialValue, + combine, + ], + ), + ), + ) as _i3.Future); + @override + _i3.Future join([String? separator = r'']) => (super.noSuchMethod( + Invocation.method( + #join, + [separator], + ), + returnValue: _i3.Future.value(''), + returnValueForMissingStub: _i3.Future.value(''), + ) as _i3.Future); + @override + _i3.Future contains(Object? needle) => (super.noSuchMethod( + Invocation.method( + #contains, + [needle], + ), + returnValue: _i3.Future.value(false), + returnValueForMissingStub: _i3.Future.value(false), + ) as _i3.Future); + @override + _i3.Future forEach(void Function(_i2.DBusSignal)? action) => + (super.noSuchMethod( + Invocation.method( + #forEach, + [action], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); + @override + _i3.Future every(bool Function(_i2.DBusSignal)? test) => + (super.noSuchMethod( + Invocation.method( + #every, + [test], + ), + returnValue: _i3.Future.value(false), + returnValueForMissingStub: _i3.Future.value(false), + ) as _i3.Future); + @override + _i3.Future any(bool Function(_i2.DBusSignal)? test) => + (super.noSuchMethod( + Invocation.method( + #any, + [test], + ), + returnValue: _i3.Future.value(false), + returnValueForMissingStub: _i3.Future.value(false), + ) as _i3.Future); + @override + _i3.Stream cast() => (super.noSuchMethod( + Invocation.method( + #cast, + [], + ), + returnValue: _i3.Stream.empty(), + returnValueForMissingStub: _i3.Stream.empty(), + ) as _i3.Stream); + @override + _i3.Future> toList() => (super.noSuchMethod( + Invocation.method( + #toList, + [], + ), + returnValue: _i3.Future>.value(<_i2.DBusSignal>[]), + returnValueForMissingStub: + _i3.Future>.value(<_i2.DBusSignal>[]), + ) as _i3.Future>); + @override + _i3.Future> toSet() => (super.noSuchMethod( + Invocation.method( + #toSet, + [], + ), + returnValue: _i3.Future>.value(<_i2.DBusSignal>{}), + returnValueForMissingStub: + _i3.Future>.value(<_i2.DBusSignal>{}), + ) as _i3.Future>); + @override + _i3.Future drain([E? futureValue]) => (super.noSuchMethod( + Invocation.method( + #drain, + [futureValue], + ), + returnValue: _FakeFuture_4( + this, + Invocation.method( + #drain, + [futureValue], + ), + ), + returnValueForMissingStub: _FakeFuture_4( + this, + Invocation.method( + #drain, + [futureValue], + ), + ), + ) as _i3.Future); + @override + _i3.Stream<_i2.DBusSignal> take(int? count) => (super.noSuchMethod( + Invocation.method( + #take, + [count], + ), + returnValue: _i3.Stream<_i2.DBusSignal>.empty(), + returnValueForMissingStub: _i3.Stream<_i2.DBusSignal>.empty(), + ) as _i3.Stream<_i2.DBusSignal>); + @override + _i3.Stream<_i2.DBusSignal> takeWhile(bool Function(_i2.DBusSignal)? test) => + (super.noSuchMethod( + Invocation.method( + #takeWhile, + [test], + ), + returnValue: _i3.Stream<_i2.DBusSignal>.empty(), + returnValueForMissingStub: _i3.Stream<_i2.DBusSignal>.empty(), + ) as _i3.Stream<_i2.DBusSignal>); + @override + _i3.Stream<_i2.DBusSignal> skip(int? count) => (super.noSuchMethod( + Invocation.method( + #skip, + [count], + ), + returnValue: _i3.Stream<_i2.DBusSignal>.empty(), + returnValueForMissingStub: _i3.Stream<_i2.DBusSignal>.empty(), + ) as _i3.Stream<_i2.DBusSignal>); + @override + _i3.Stream<_i2.DBusSignal> skipWhile(bool Function(_i2.DBusSignal)? test) => + (super.noSuchMethod( + Invocation.method( + #skipWhile, + [test], + ), + returnValue: _i3.Stream<_i2.DBusSignal>.empty(), + returnValueForMissingStub: _i3.Stream<_i2.DBusSignal>.empty(), + ) as _i3.Stream<_i2.DBusSignal>); + @override + _i3.Stream<_i2.DBusSignal> distinct( + [bool Function( + _i2.DBusSignal, + _i2.DBusSignal, + )? equals]) => + (super.noSuchMethod( + Invocation.method( + #distinct, + [equals], + ), + returnValue: _i3.Stream<_i2.DBusSignal>.empty(), + returnValueForMissingStub: _i3.Stream<_i2.DBusSignal>.empty(), + ) as _i3.Stream<_i2.DBusSignal>); + @override + _i3.Future<_i2.DBusSignal> firstWhere( + bool Function(_i2.DBusSignal)? test, { + _i2.DBusSignal Function()? orElse, + }) => + (super.noSuchMethod( + Invocation.method( + #firstWhere, + [test], + {#orElse: orElse}, + ), + returnValue: _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #firstWhere, + [test], + {#orElse: orElse}, + ), + )), + returnValueForMissingStub: + _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #firstWhere, + [test], + {#orElse: orElse}, + ), + )), + ) as _i3.Future<_i2.DBusSignal>); + @override + _i3.Future<_i2.DBusSignal> lastWhere( + bool Function(_i2.DBusSignal)? test, { + _i2.DBusSignal Function()? orElse, + }) => + (super.noSuchMethod( + Invocation.method( + #lastWhere, + [test], + {#orElse: orElse}, + ), + returnValue: _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #lastWhere, + [test], + {#orElse: orElse}, + ), + )), + returnValueForMissingStub: + _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #lastWhere, + [test], + {#orElse: orElse}, + ), + )), + ) as _i3.Future<_i2.DBusSignal>); + @override + _i3.Future<_i2.DBusSignal> singleWhere( + bool Function(_i2.DBusSignal)? test, { + _i2.DBusSignal Function()? orElse, + }) => + (super.noSuchMethod( + Invocation.method( + #singleWhere, + [test], + {#orElse: orElse}, + ), + returnValue: _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #singleWhere, + [test], + {#orElse: orElse}, + ), + )), + returnValueForMissingStub: + _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #singleWhere, + [test], + {#orElse: orElse}, + ), + )), + ) as _i3.Future<_i2.DBusSignal>); + @override + _i3.Future<_i2.DBusSignal> elementAt(int? index) => (super.noSuchMethod( + Invocation.method( + #elementAt, + [index], + ), + returnValue: _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #elementAt, + [index], + ), + )), + returnValueForMissingStub: + _i3.Future<_i2.DBusSignal>.value(_FakeDBusSignal_2( + this, + Invocation.method( + #elementAt, + [index], + ), + )), + ) as _i3.Future<_i2.DBusSignal>); + @override + _i3.Stream<_i2.DBusSignal> timeout( + Duration? timeLimit, { + void Function(_i3.EventSink<_i2.DBusSignal>)? onTimeout, + }) => + (super.noSuchMethod( + Invocation.method( + #timeout, + [timeLimit], + {#onTimeout: onTimeout}, + ), + returnValue: _i3.Stream<_i2.DBusSignal>.empty(), + returnValueForMissingStub: _i3.Stream<_i2.DBusSignal>.empty(), + ) as _i3.Stream<_i2.DBusSignal>); +} + +/// A class which mocks [LinuxPlatformInfo]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockLinuxPlatformInfo extends _i1.Mock implements _i4.LinuxPlatformInfo { + @override + _i3.Future<_i4.LinuxPlatformInfoData> getAll() => (super.noSuchMethod( + Invocation.method( + #getAll, + [], + ), + returnValue: _i3.Future<_i4.LinuxPlatformInfoData>.value( + _FakeLinuxPlatformInfoData_5( + this, + Invocation.method( + #getAll, + [], + ), + )), + returnValueForMissingStub: _i3.Future<_i4.LinuxPlatformInfoData>.value( + _FakeLinuxPlatformInfoData_5( + this, + Invocation.method( + #getAll, + [], + ), + )), + ) as _i3.Future<_i4.LinuxPlatformInfoData>); +} + +/// A class which mocks [NotificationStorage]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockNotificationStorage extends _i1.Mock + implements _i6.NotificationStorage { + @override + _i3.Future> getAll() => (super.noSuchMethod( + Invocation.method( + #getAll, + [], + ), + returnValue: _i3.Future>.value( + <_i7.LinuxNotificationInfo>[]), + returnValueForMissingStub: + _i3.Future>.value( + <_i7.LinuxNotificationInfo>[]), + ) as _i3.Future>); + @override + _i3.Future<_i7.LinuxNotificationInfo?> getBySystemId(int? systemId) => + (super.noSuchMethod( + Invocation.method( + #getBySystemId, + [systemId], + ), + returnValue: _i3.Future<_i7.LinuxNotificationInfo?>.value(), + returnValueForMissingStub: + _i3.Future<_i7.LinuxNotificationInfo?>.value(), + ) as _i3.Future<_i7.LinuxNotificationInfo?>); + @override + _i3.Future<_i7.LinuxNotificationInfo?> getById(int? id) => + (super.noSuchMethod( + Invocation.method( + #getById, + [id], + ), + returnValue: _i3.Future<_i7.LinuxNotificationInfo?>.value(), + returnValueForMissingStub: + _i3.Future<_i7.LinuxNotificationInfo?>.value(), + ) as _i3.Future<_i7.LinuxNotificationInfo?>); + @override + _i3.Future insert(_i7.LinuxNotificationInfo? notification) => + (super.noSuchMethod( + Invocation.method( + #insert, + [notification], + ), + returnValue: _i3.Future.value(false), + returnValueForMissingStub: _i3.Future.value(false), + ) as _i3.Future); + @override + _i3.Future removeById(int? id) => (super.noSuchMethod( + Invocation.method( + #removeById, + [id], + ), + returnValue: _i3.Future.value(false), + returnValueForMissingStub: _i3.Future.value(false), + ) as _i3.Future); + @override + _i3.Future removeBySystemId(int? systemId) => (super.noSuchMethod( + Invocation.method( + #removeBySystemId, + [systemId], + ), + returnValue: _i3.Future.value(false), + returnValueForMissingStub: _i3.Future.value(false), + ) as _i3.Future); + @override + _i3.Future removeByIdList(List? idList) => (super.noSuchMethod( + Invocation.method( + #removeByIdList, + [idList], + ), + returnValue: _i3.Future.value(false), + returnValueForMissingStub: _i3.Future.value(false), + ) as _i3.Future); + @override + _i3.Future forceReloadCache() => (super.noSuchMethod( + Invocation.method( + #forceReloadCache, + [], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); +} + +/// A class which mocks [DidReceiveNotificationResponseCallback]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDidReceiveNotificationResponseCallback extends _i1.Mock + implements _i8.DidReceiveNotificationResponseCallback { + @override + _i3.Future call(_i9.NotificationResponse? notificationResponse) => + (super.noSuchMethod( + Invocation.method( + #call, + [notificationResponse], + ), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) as _i3.Future); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/posix_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/posix_test.dart new file mode 100755 index 00000000..4ec9b406 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/posix_test.dart @@ -0,0 +1,18 @@ +import 'dart:io'; + +import 'package:flutter_local_notifications_linux/src/posix.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('POSIX |', () { + late Posix posix; + + setUpAll(() { + posix = Posix(); + }); + + test('getpid', () { + expect(posix.getpid(), equals(pid)); + }); + }, skip: !Platform.isLinux); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/storage_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/storage_test.dart new file mode 100755 index 00000000..61ead727 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/storage_test.dart @@ -0,0 +1,288 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter_local_notifications_linux/src/file_system.dart'; +import 'package:flutter_local_notifications_linux/src/notification_info.dart'; +import 'package:flutter_local_notifications_linux/src/platform_info.dart'; +import 'package:flutter_local_notifications_linux/src/storage.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:path/path.dart' as path; + +@GenerateNiceMocks(>[ + MockSpec(), + MockSpec(), + MockSpec(), +]) +import 'storage_test.mocks.dart'; + +void main() { + group('Notification storage |', () { + late NotificationStorage storage; + late final MockLinuxPlatformInfo mockPlatformInfo; + late final MockFileSystem mockFs; + late final MockFile mockStorageFile; + + const LinuxPlatformInfoData platformInfo = LinuxPlatformInfoData( + appName: 'Test', + assetsPath: 'assets', + runtimePath: 'run', + ); + + final String fileStoragePath = path.join( + platformInfo.runtimePath!, + 'notification_plugin_cache.json', + ); + + setUpAll(() { + mockPlatformInfo = MockLinuxPlatformInfo(); + mockFs = MockFileSystem(); + mockStorageFile = MockFile(); + + when( + mockPlatformInfo.getAll(), + ).thenAnswer((_) async => platformInfo); + when(mockFs.open(fileStoragePath)).thenReturn(mockStorageFile); + }); + + setUp(() { + storage = NotificationStorage( + platformInfo: mockPlatformInfo, + fs: mockFs, + ); + }); + + test('Insert', () async { + const List notifications = [ + LinuxNotificationInfo(id: 1, systemId: 1), + LinuxNotificationInfo( + id: 2, + systemId: 2, + payload: 'test', + ), + LinuxNotificationInfo( + id: 3, + systemId: 3, + payload: 'test', + actions: [ + LinuxNotificationActionInfo(key: '1'), + LinuxNotificationActionInfo(key: '2'), + ], + ), + ]; + + when(mockStorageFile.existsSync()).thenReturn(false); + when( + mockStorageFile.createSync(recursive: true), + ).thenAnswer((_) {}); + when( + mockStorageFile.writeAsStringSync(any), + ).thenAnswer((_) {}); + when(mockStorageFile.readAsStringSync()).thenReturn(''); + + expect(await storage.insert(notifications[0]), isTrue); + expect(await storage.insert(notifications[1]), isTrue); + expect(await storage.insert(notifications[2]), isTrue); + + verify( + mockStorageFile.createSync(recursive: true), + ).called(3); + verify( + mockStorageFile.writeAsStringSync( + jsonEncode([notifications[0]]), + ), + ).called(1); + verify( + mockStorageFile.writeAsStringSync(jsonEncode(notifications)), + ).called(1); + }); + + test('Remove', () async { + const List notifications = [ + LinuxNotificationInfo(id: 1, systemId: 1), + LinuxNotificationInfo( + id: 2, + systemId: 2, + payload: 'test', + ), + ]; + + when(mockStorageFile.existsSync()).thenReturn(true); + when( + mockStorageFile.writeAsStringSync(any), + ).thenAnswer((_) {}); + when(mockStorageFile.readAsStringSync()).thenReturn(''); + + await storage.insert(notifications[0]); + await storage.insert(notifications[1]); + + expect(await storage.removeById(notifications[0].id), isTrue); + expect(await storage.removeById(notifications[1].id), isTrue); + + verify( + mockStorageFile.writeAsStringSync( + jsonEncode([notifications[1]]), + ), + ).called(1); + verify( + mockStorageFile.writeAsStringSync( + jsonEncode([]), + ), + ).called(1); + }); + + test('Get all', () async { + const List notifications = [ + LinuxNotificationInfo(id: 1, systemId: 1), + LinuxNotificationInfo( + id: 2, + systemId: 2, + payload: 'test', + ), + LinuxNotificationInfo( + id: 3, + systemId: 3, + payload: 'test', + actions: [ + LinuxNotificationActionInfo(key: '1'), + LinuxNotificationActionInfo(key: '2'), + ]), + ]; + + when(mockStorageFile.existsSync()).thenReturn(true); + when( + mockStorageFile.writeAsStringSync(any), + ).thenAnswer((_) {}); + + when(mockStorageFile.readAsStringSync()).thenReturn(''); + expect(await storage.getAll(), []); + + when( + mockStorageFile.readAsStringSync(), + ).thenReturn(jsonEncode([])); + expect(await storage.getAll(), []); + + when( + mockStorageFile.readAsStringSync(), + ).thenReturn(jsonEncode(notifications)); + await storage.insert(notifications[0]); + await storage.insert(notifications[1]); + await storage.insert(notifications[2]); + + expect( + await storage.getAll(), + notifications, + ); + }); + + test('Get by ID', () async { + const LinuxNotificationInfo notification = LinuxNotificationInfo( + id: 1, + systemId: 1, + ); + + when(mockStorageFile.existsSync()).thenReturn(true); + when( + mockStorageFile.writeAsStringSync(any), + ).thenAnswer((_) {}); + + when(mockStorageFile.readAsStringSync()).thenReturn(''); + expect(await storage.getAll(), []); + + when( + mockStorageFile.readAsStringSync(), + ).thenReturn(jsonEncode([])); + expect(await storage.getAll(), []); + + when( + mockStorageFile.readAsStringSync(), + ).thenReturn(jsonEncode(notification)); + await storage.insert(notification); + + expect(await storage.getById(2), isNull); + expect(await storage.getById(notification.id), notification); + }); + + test('Get by system ID', () async { + const LinuxNotificationInfo notification = LinuxNotificationInfo( + id: 1, + systemId: 2, + ); + + when(mockStorageFile.existsSync()).thenReturn(true); + when( + mockStorageFile.writeAsStringSync(any), + ).thenAnswer((_) {}); + + when( + mockStorageFile.readAsStringSync(), + ).thenReturn(jsonEncode(notification)); + await storage.insert(notification); + + expect(await storage.getBySystemId(notification.systemId), notification); + }); + + test('Get all, file does not exist', () async { + when(mockStorageFile.existsSync()).thenReturn(false); + expect(await storage.getAll(), []); + }); + + test('Remove by ID list', () async { + const List notifications = [ + LinuxNotificationInfo(id: 1, systemId: 1), + LinuxNotificationInfo( + id: 2, + systemId: 2, + payload: 'test', + ), + ]; + + when(mockStorageFile.existsSync()).thenReturn(true); + when( + mockStorageFile.writeAsStringSync(any), + ).thenAnswer((_) {}); + when(mockStorageFile.readAsStringSync()).thenReturn(''); + + await storage.insert(notifications[0]); + await storage.insert(notifications[1]); + + expect( + await storage.removeByIdList( + notifications.map((LinuxNotificationInfo n) => n.id).toList(), + ), + isTrue, + ); + expect(await storage.getAll(), []); + + verify( + mockStorageFile.writeAsStringSync( + jsonEncode([]), + ), + ).called(1); + }); + + test('Remove by system ID', () async { + const LinuxNotificationInfo notification = LinuxNotificationInfo( + id: 1, + systemId: 2, + ); + + when(mockStorageFile.existsSync()).thenReturn(true); + when( + mockStorageFile.writeAsStringSync(any), + ).thenAnswer((_) {}); + when(mockStorageFile.readAsStringSync()).thenReturn(''); + + await storage.insert(notification); + + expect(await storage.removeBySystemId(notification.systemId), isTrue); + + verify( + mockStorageFile.writeAsStringSync( + jsonEncode([]), + ), + ).called(1); + }); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/storage_test.mocks.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/storage_test.mocks.dart new file mode 100755 index 00000000..d82257e0 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_linux/test/storage_test.mocks.dart @@ -0,0 +1,921 @@ +// Mocks generated by Mockito 5.4.0 from annotations +// in flutter_local_notifications_linux/test/storage_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i4; +import 'dart:convert' as _i6; +import 'dart:io' as _i3; +import 'dart:typed_data' as _i7; + +import 'package:flutter_local_notifications_linux/src/file_system.dart' as _i5; +import 'package:flutter_local_notifications_linux/src/platform_info.dart' + as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeLinuxPlatformInfoData_0 extends _i1.SmartFake + implements _i2.LinuxPlatformInfoData { + _FakeLinuxPlatformInfoData_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFile_1 extends _i1.SmartFake implements _i3.File { + _FakeFile_1( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeUri_2 extends _i1.SmartFake implements Uri { + _FakeUri_2( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDirectory_3 extends _i1.SmartFake implements _i3.Directory { + _FakeDirectory_3( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeDateTime_4 extends _i1.SmartFake implements DateTime { + _FakeDateTime_4( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeRandomAccessFile_5 extends _i1.SmartFake + implements _i3.RandomAccessFile { + _FakeRandomAccessFile_5( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeIOSink_6 extends _i1.SmartFake implements _i3.IOSink { + _FakeIOSink_6( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFileStat_7 extends _i1.SmartFake implements _i3.FileStat { + _FakeFileStat_7( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +class _FakeFileSystemEntity_8 extends _i1.SmartFake + implements _i3.FileSystemEntity { + _FakeFileSystemEntity_8( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [LinuxPlatformInfo]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockLinuxPlatformInfo extends _i1.Mock implements _i2.LinuxPlatformInfo { + @override + _i4.Future<_i2.LinuxPlatformInfoData> getAll() => (super.noSuchMethod( + Invocation.method( + #getAll, + [], + ), + returnValue: _i4.Future<_i2.LinuxPlatformInfoData>.value( + _FakeLinuxPlatformInfoData_0( + this, + Invocation.method( + #getAll, + [], + ), + )), + returnValueForMissingStub: _i4.Future<_i2.LinuxPlatformInfoData>.value( + _FakeLinuxPlatformInfoData_0( + this, + Invocation.method( + #getAll, + [], + ), + )), + ) as _i4.Future<_i2.LinuxPlatformInfoData>); +} + +/// A class which mocks [FileSystem]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFileSystem extends _i1.Mock implements _i5.FileSystem { + @override + _i3.File open(String? path) => (super.noSuchMethod( + Invocation.method( + #open, + [path], + ), + returnValue: _FakeFile_1( + this, + Invocation.method( + #open, + [path], + ), + ), + returnValueForMissingStub: _FakeFile_1( + this, + Invocation.method( + #open, + [path], + ), + ), + ) as _i3.File); +} + +/// A class which mocks [File]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFile extends _i1.Mock implements _i3.File { + @override + _i3.File get absolute => (super.noSuchMethod( + Invocation.getter(#absolute), + returnValue: _FakeFile_1( + this, + Invocation.getter(#absolute), + ), + returnValueForMissingStub: _FakeFile_1( + this, + Invocation.getter(#absolute), + ), + ) as _i3.File); + @override + String get path => (super.noSuchMethod( + Invocation.getter(#path), + returnValue: '', + returnValueForMissingStub: '', + ) as String); + @override + Uri get uri => (super.noSuchMethod( + Invocation.getter(#uri), + returnValue: _FakeUri_2( + this, + Invocation.getter(#uri), + ), + returnValueForMissingStub: _FakeUri_2( + this, + Invocation.getter(#uri), + ), + ) as Uri); + @override + bool get isAbsolute => (super.noSuchMethod( + Invocation.getter(#isAbsolute), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + @override + _i3.Directory get parent => (super.noSuchMethod( + Invocation.getter(#parent), + returnValue: _FakeDirectory_3( + this, + Invocation.getter(#parent), + ), + returnValueForMissingStub: _FakeDirectory_3( + this, + Invocation.getter(#parent), + ), + ) as _i3.Directory); + @override + _i4.Future<_i3.File> create({ + bool? recursive = false, + bool? exclusive = false, + }) => + (super.noSuchMethod( + Invocation.method( + #create, + [], + { + #recursive: recursive, + #exclusive: exclusive, + }, + ), + returnValue: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #create, + [], + { + #recursive: recursive, + #exclusive: exclusive, + }, + ), + )), + returnValueForMissingStub: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #create, + [], + { + #recursive: recursive, + #exclusive: exclusive, + }, + ), + )), + ) as _i4.Future<_i3.File>); + @override + void createSync({ + bool? recursive = false, + bool? exclusive = false, + }) => + super.noSuchMethod( + Invocation.method( + #createSync, + [], + { + #recursive: recursive, + #exclusive: exclusive, + }, + ), + returnValueForMissingStub: null, + ); + @override + _i4.Future<_i3.File> rename(String? newPath) => (super.noSuchMethod( + Invocation.method( + #rename, + [newPath], + ), + returnValue: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #rename, + [newPath], + ), + )), + returnValueForMissingStub: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #rename, + [newPath], + ), + )), + ) as _i4.Future<_i3.File>); + @override + _i3.File renameSync(String? newPath) => (super.noSuchMethod( + Invocation.method( + #renameSync, + [newPath], + ), + returnValue: _FakeFile_1( + this, + Invocation.method( + #renameSync, + [newPath], + ), + ), + returnValueForMissingStub: _FakeFile_1( + this, + Invocation.method( + #renameSync, + [newPath], + ), + ), + ) as _i3.File); + @override + _i4.Future<_i3.File> copy(String? newPath) => (super.noSuchMethod( + Invocation.method( + #copy, + [newPath], + ), + returnValue: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #copy, + [newPath], + ), + )), + returnValueForMissingStub: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #copy, + [newPath], + ), + )), + ) as _i4.Future<_i3.File>); + @override + _i3.File copySync(String? newPath) => (super.noSuchMethod( + Invocation.method( + #copySync, + [newPath], + ), + returnValue: _FakeFile_1( + this, + Invocation.method( + #copySync, + [newPath], + ), + ), + returnValueForMissingStub: _FakeFile_1( + this, + Invocation.method( + #copySync, + [newPath], + ), + ), + ) as _i3.File); + @override + _i4.Future length() => (super.noSuchMethod( + Invocation.method( + #length, + [], + ), + returnValue: _i4.Future.value(0), + returnValueForMissingStub: _i4.Future.value(0), + ) as _i4.Future); + @override + int lengthSync() => (super.noSuchMethod( + Invocation.method( + #lengthSync, + [], + ), + returnValue: 0, + returnValueForMissingStub: 0, + ) as int); + @override + _i4.Future lastAccessed() => (super.noSuchMethod( + Invocation.method( + #lastAccessed, + [], + ), + returnValue: _i4.Future.value(_FakeDateTime_4( + this, + Invocation.method( + #lastAccessed, + [], + ), + )), + returnValueForMissingStub: _i4.Future.value(_FakeDateTime_4( + this, + Invocation.method( + #lastAccessed, + [], + ), + )), + ) as _i4.Future); + @override + DateTime lastAccessedSync() => (super.noSuchMethod( + Invocation.method( + #lastAccessedSync, + [], + ), + returnValue: _FakeDateTime_4( + this, + Invocation.method( + #lastAccessedSync, + [], + ), + ), + returnValueForMissingStub: _FakeDateTime_4( + this, + Invocation.method( + #lastAccessedSync, + [], + ), + ), + ) as DateTime); + @override + _i4.Future setLastAccessed(DateTime? time) => (super.noSuchMethod( + Invocation.method( + #setLastAccessed, + [time], + ), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); + @override + void setLastAccessedSync(DateTime? time) => super.noSuchMethod( + Invocation.method( + #setLastAccessedSync, + [time], + ), + returnValueForMissingStub: null, + ); + @override + _i4.Future lastModified() => (super.noSuchMethod( + Invocation.method( + #lastModified, + [], + ), + returnValue: _i4.Future.value(_FakeDateTime_4( + this, + Invocation.method( + #lastModified, + [], + ), + )), + returnValueForMissingStub: _i4.Future.value(_FakeDateTime_4( + this, + Invocation.method( + #lastModified, + [], + ), + )), + ) as _i4.Future); + @override + DateTime lastModifiedSync() => (super.noSuchMethod( + Invocation.method( + #lastModifiedSync, + [], + ), + returnValue: _FakeDateTime_4( + this, + Invocation.method( + #lastModifiedSync, + [], + ), + ), + returnValueForMissingStub: _FakeDateTime_4( + this, + Invocation.method( + #lastModifiedSync, + [], + ), + ), + ) as DateTime); + @override + _i4.Future setLastModified(DateTime? time) => (super.noSuchMethod( + Invocation.method( + #setLastModified, + [time], + ), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); + @override + void setLastModifiedSync(DateTime? time) => super.noSuchMethod( + Invocation.method( + #setLastModifiedSync, + [time], + ), + returnValueForMissingStub: null, + ); + @override + _i4.Future<_i3.RandomAccessFile> open( + {_i3.FileMode? mode = _i3.FileMode.read}) => + (super.noSuchMethod( + Invocation.method( + #open, + [], + {#mode: mode}, + ), + returnValue: + _i4.Future<_i3.RandomAccessFile>.value(_FakeRandomAccessFile_5( + this, + Invocation.method( + #open, + [], + {#mode: mode}, + ), + )), + returnValueForMissingStub: + _i4.Future<_i3.RandomAccessFile>.value(_FakeRandomAccessFile_5( + this, + Invocation.method( + #open, + [], + {#mode: mode}, + ), + )), + ) as _i4.Future<_i3.RandomAccessFile>); + @override + _i3.RandomAccessFile openSync({_i3.FileMode? mode = _i3.FileMode.read}) => + (super.noSuchMethod( + Invocation.method( + #openSync, + [], + {#mode: mode}, + ), + returnValue: _FakeRandomAccessFile_5( + this, + Invocation.method( + #openSync, + [], + {#mode: mode}, + ), + ), + returnValueForMissingStub: _FakeRandomAccessFile_5( + this, + Invocation.method( + #openSync, + [], + {#mode: mode}, + ), + ), + ) as _i3.RandomAccessFile); + @override + _i4.Stream> openRead([ + int? start, + int? end, + ]) => + (super.noSuchMethod( + Invocation.method( + #openRead, + [ + start, + end, + ], + ), + returnValue: _i4.Stream>.empty(), + returnValueForMissingStub: _i4.Stream>.empty(), + ) as _i4.Stream>); + @override + _i3.IOSink openWrite({ + _i3.FileMode? mode = _i3.FileMode.write, + _i6.Encoding? encoding = const _i6.Utf8Codec(), + }) => + (super.noSuchMethod( + Invocation.method( + #openWrite, + [], + { + #mode: mode, + #encoding: encoding, + }, + ), + returnValue: _FakeIOSink_6( + this, + Invocation.method( + #openWrite, + [], + { + #mode: mode, + #encoding: encoding, + }, + ), + ), + returnValueForMissingStub: _FakeIOSink_6( + this, + Invocation.method( + #openWrite, + [], + { + #mode: mode, + #encoding: encoding, + }, + ), + ), + ) as _i3.IOSink); + @override + _i4.Future<_i7.Uint8List> readAsBytes() => (super.noSuchMethod( + Invocation.method( + #readAsBytes, + [], + ), + returnValue: _i4.Future<_i7.Uint8List>.value(_i7.Uint8List(0)), + returnValueForMissingStub: + _i4.Future<_i7.Uint8List>.value(_i7.Uint8List(0)), + ) as _i4.Future<_i7.Uint8List>); + @override + _i7.Uint8List readAsBytesSync() => (super.noSuchMethod( + Invocation.method( + #readAsBytesSync, + [], + ), + returnValue: _i7.Uint8List(0), + returnValueForMissingStub: _i7.Uint8List(0), + ) as _i7.Uint8List); + @override + _i4.Future readAsString( + {_i6.Encoding? encoding = const _i6.Utf8Codec()}) => + (super.noSuchMethod( + Invocation.method( + #readAsString, + [], + {#encoding: encoding}, + ), + returnValue: _i4.Future.value(''), + returnValueForMissingStub: _i4.Future.value(''), + ) as _i4.Future); + @override + String readAsStringSync({_i6.Encoding? encoding = const _i6.Utf8Codec()}) => + (super.noSuchMethod( + Invocation.method( + #readAsStringSync, + [], + {#encoding: encoding}, + ), + returnValue: '', + returnValueForMissingStub: '', + ) as String); + @override + _i4.Future> readAsLines( + {_i6.Encoding? encoding = const _i6.Utf8Codec()}) => + (super.noSuchMethod( + Invocation.method( + #readAsLines, + [], + {#encoding: encoding}, + ), + returnValue: _i4.Future>.value([]), + returnValueForMissingStub: _i4.Future>.value([]), + ) as _i4.Future>); + @override + List readAsLinesSync( + {_i6.Encoding? encoding = const _i6.Utf8Codec()}) => + (super.noSuchMethod( + Invocation.method( + #readAsLinesSync, + [], + {#encoding: encoding}, + ), + returnValue: [], + returnValueForMissingStub: [], + ) as List); + @override + _i4.Future<_i3.File> writeAsBytes( + List? bytes, { + _i3.FileMode? mode = _i3.FileMode.write, + bool? flush = false, + }) => + (super.noSuchMethod( + Invocation.method( + #writeAsBytes, + [bytes], + { + #mode: mode, + #flush: flush, + }, + ), + returnValue: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #writeAsBytes, + [bytes], + { + #mode: mode, + #flush: flush, + }, + ), + )), + returnValueForMissingStub: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #writeAsBytes, + [bytes], + { + #mode: mode, + #flush: flush, + }, + ), + )), + ) as _i4.Future<_i3.File>); + @override + void writeAsBytesSync( + List? bytes, { + _i3.FileMode? mode = _i3.FileMode.write, + bool? flush = false, + }) => + super.noSuchMethod( + Invocation.method( + #writeAsBytesSync, + [bytes], + { + #mode: mode, + #flush: flush, + }, + ), + returnValueForMissingStub: null, + ); + @override + _i4.Future<_i3.File> writeAsString( + String? contents, { + _i3.FileMode? mode = _i3.FileMode.write, + _i6.Encoding? encoding = const _i6.Utf8Codec(), + bool? flush = false, + }) => + (super.noSuchMethod( + Invocation.method( + #writeAsString, + [contents], + { + #mode: mode, + #encoding: encoding, + #flush: flush, + }, + ), + returnValue: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #writeAsString, + [contents], + { + #mode: mode, + #encoding: encoding, + #flush: flush, + }, + ), + )), + returnValueForMissingStub: _i4.Future<_i3.File>.value(_FakeFile_1( + this, + Invocation.method( + #writeAsString, + [contents], + { + #mode: mode, + #encoding: encoding, + #flush: flush, + }, + ), + )), + ) as _i4.Future<_i3.File>); + @override + void writeAsStringSync( + String? contents, { + _i3.FileMode? mode = _i3.FileMode.write, + _i6.Encoding? encoding = const _i6.Utf8Codec(), + bool? flush = false, + }) => + super.noSuchMethod( + Invocation.method( + #writeAsStringSync, + [contents], + { + #mode: mode, + #encoding: encoding, + #flush: flush, + }, + ), + returnValueForMissingStub: null, + ); + @override + _i4.Future exists() => (super.noSuchMethod( + Invocation.method( + #exists, + [], + ), + returnValue: _i4.Future.value(false), + returnValueForMissingStub: _i4.Future.value(false), + ) as _i4.Future); + @override + bool existsSync() => (super.noSuchMethod( + Invocation.method( + #existsSync, + [], + ), + returnValue: false, + returnValueForMissingStub: false, + ) as bool); + @override + _i4.Future resolveSymbolicLinks() => (super.noSuchMethod( + Invocation.method( + #resolveSymbolicLinks, + [], + ), + returnValue: _i4.Future.value(''), + returnValueForMissingStub: _i4.Future.value(''), + ) as _i4.Future); + @override + String resolveSymbolicLinksSync() => (super.noSuchMethod( + Invocation.method( + #resolveSymbolicLinksSync, + [], + ), + returnValue: '', + returnValueForMissingStub: '', + ) as String); + @override + _i4.Future<_i3.FileStat> stat() => (super.noSuchMethod( + Invocation.method( + #stat, + [], + ), + returnValue: _i4.Future<_i3.FileStat>.value(_FakeFileStat_7( + this, + Invocation.method( + #stat, + [], + ), + )), + returnValueForMissingStub: + _i4.Future<_i3.FileStat>.value(_FakeFileStat_7( + this, + Invocation.method( + #stat, + [], + ), + )), + ) as _i4.Future<_i3.FileStat>); + @override + _i3.FileStat statSync() => (super.noSuchMethod( + Invocation.method( + #statSync, + [], + ), + returnValue: _FakeFileStat_7( + this, + Invocation.method( + #statSync, + [], + ), + ), + returnValueForMissingStub: _FakeFileStat_7( + this, + Invocation.method( + #statSync, + [], + ), + ), + ) as _i3.FileStat); + @override + _i4.Future<_i3.FileSystemEntity> delete({bool? recursive = false}) => + (super.noSuchMethod( + Invocation.method( + #delete, + [], + {#recursive: recursive}, + ), + returnValue: + _i4.Future<_i3.FileSystemEntity>.value(_FakeFileSystemEntity_8( + this, + Invocation.method( + #delete, + [], + {#recursive: recursive}, + ), + )), + returnValueForMissingStub: + _i4.Future<_i3.FileSystemEntity>.value(_FakeFileSystemEntity_8( + this, + Invocation.method( + #delete, + [], + {#recursive: recursive}, + ), + )), + ) as _i4.Future<_i3.FileSystemEntity>); + @override + void deleteSync({bool? recursive = false}) => super.noSuchMethod( + Invocation.method( + #deleteSync, + [], + {#recursive: recursive}, + ), + returnValueForMissingStub: null, + ); + @override + _i4.Stream<_i3.FileSystemEvent> watch({ + int? events = 15, + bool? recursive = false, + }) => + (super.noSuchMethod( + Invocation.method( + #watch, + [], + { + #events: events, + #recursive: recursive, + }, + ), + returnValue: _i4.Stream<_i3.FileSystemEvent>.empty(), + returnValueForMissingStub: _i4.Stream<_i3.FileSystemEvent>.empty(), + ) as _i4.Stream<_i3.FileSystemEvent>); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux deleted file mode 120000 index f478642a..00000000 --- a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/image_picker_linux-0.2.1+2/ \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/AUTHORS b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/AUTHORS new file mode 100755 index 00000000..26e81c7f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/AUTHORS @@ -0,0 +1,7 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. +Alexandre Zollinger Chohfi diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/CHANGELOG.md b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/CHANGELOG.md new file mode 100755 index 00000000..f54ebd50 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/CHANGELOG.md @@ -0,0 +1,17 @@ +## 0.2.1+2 + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. +* Fixes `getMedia` mime types. + +## 0.2.1+1 + +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. + +## 0.2.1 + +* Adds `getMedia` method. + +## 0.2.0 + +* Implements initial Linux support. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/LICENSE b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/LICENSE new file mode 100755 index 00000000..c6823b81 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/README.md new file mode 100755 index 00000000..55b58356 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/README.md @@ -0,0 +1,27 @@ +# image\_picker\_linux + +A Linux implementation of [`image_picker`][1]. + +## Limitations + +`ImageSource.camera` is not supported unless a `cameraDelegate` is set. + +### pickImage() +The arguments `maxWidth`, `maxHeight`, and `imageQuality` are not currently supported. + +### pickVideo() +The argument `maxDuration` is not currently supported. + +## Usage + +### Import the package + +This package is [endorsed][2], which means you can simply use `file_selector` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. + +[1]: https://pub.dev/packages/image_picker +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/README.md new file mode 100755 index 00000000..96b8bb17 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/lib/main.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/lib/main.dart new file mode 100755 index 00000000..8f488709 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/lib/main.dart @@ -0,0 +1,516 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; +import 'package:mime/mime.dart'; +import 'package:video_player/video_player.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + title: 'Image Picker Demo', + home: MyHomePage(title: 'Image Picker Example'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, this.title}); + + final String? title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + List? _mediaFileList; + + // This must be called from within a setState() callback + void _setImageFileListFromFile(XFile? value) { + _mediaFileList = value == null ? null : [value]; + } + + dynamic _pickImageError; + bool _isVideo = false; + + VideoPlayerController? _controller; + VideoPlayerController? _toBeDisposed; + String? _retrieveDataError; + + final ImagePickerPlatform _picker = ImagePickerPlatform.instance; + final TextEditingController maxWidthController = TextEditingController(); + final TextEditingController maxHeightController = TextEditingController(); + final TextEditingController qualityController = TextEditingController(); + + Future _playVideo(XFile? file) async { + if (file != null && mounted) { + await _disposeVideoController(); + final VideoPlayerController controller = + VideoPlayerController.file(File(file.path)); + _controller = controller; + await controller.setVolume(1.0); + await controller.initialize(); + await controller.setLooping(true); + await controller.play(); + setState(() {}); + } + } + + Future _onImageButtonPressed( + ImageSource source, { + required BuildContext context, + bool isMultiImage = false, + bool isMedia = false, + }) async { + if (_controller != null) { + await _controller!.setVolume(0.0); + } + if (context.mounted) { + if (_isVideo) { + final XFile? file = await _picker.getVideo( + source: source, maxDuration: const Duration(seconds: 10)); + await _playVideo(file); + } else if (isMultiImage) { + await _displayPickImageDialog(context, + (double? maxWidth, double? maxHeight, int? quality) async { + try { + final List pickedFileList = isMedia + ? await _picker.getMedia( + options: MediaOptions( + allowMultiple: isMultiImage, + imageOptions: ImageOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + )), + ) + : await _picker.getMultiImageWithOptions( + options: MultiImagePickerOptions( + imageOptions: ImageOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + ), + ), + ); + setState(() { + _mediaFileList = pickedFileList; + }); + } catch (e) { + setState(() { + _pickImageError = e; + }); + } + }); + } else if (isMedia) { + await _displayPickImageDialog(context, + (double? maxWidth, double? maxHeight, int? quality) async { + try { + final List pickedFileList = []; + final XFile? media = _firstOrNull(await _picker.getMedia( + options: MediaOptions( + allowMultiple: isMultiImage, + imageOptions: ImageOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + )), + )); + + if (media != null) { + pickedFileList.add(media); + setState(() { + _mediaFileList = pickedFileList; + }); + } + } catch (e) { + setState(() => _pickImageError = e); + } + }); + } else { + await _displayPickImageDialog(context, + (double? maxWidth, double? maxHeight, int? quality) async { + try { + final XFile? pickedFile = await _picker.getImageFromSource( + source: source, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + ), + ); + setState(() { + _setImageFileListFromFile(pickedFile); + }); + } catch (e) { + setState(() { + _pickImageError = e; + }); + } + }); + } + } + } + + @override + void deactivate() { + if (_controller != null) { + _controller!.setVolume(0.0); + _controller!.pause(); + } + super.deactivate(); + } + + @override + void dispose() { + _disposeVideoController(); + maxWidthController.dispose(); + maxHeightController.dispose(); + qualityController.dispose(); + super.dispose(); + } + + Future _disposeVideoController() async { + if (_toBeDisposed != null) { + await _toBeDisposed!.dispose(); + } + _toBeDisposed = _controller; + _controller = null; + } + + Widget _previewVideo() { + final Text? retrieveError = _getRetrieveErrorWidget(); + if (retrieveError != null) { + return retrieveError; + } + if (_controller == null) { + return const Text( + 'You have not yet picked a video', + textAlign: TextAlign.center, + ); + } + return Padding( + padding: const EdgeInsets.all(10.0), + child: AspectRatioVideo(_controller), + ); + } + + Widget _previewImages() { + final Text? retrieveError = _getRetrieveErrorWidget(); + if (retrieveError != null) { + return retrieveError; + } + if (_mediaFileList != null) { + return Semantics( + label: 'image_picker_example_picked_images', + child: ListView.builder( + key: UniqueKey(), + itemBuilder: (BuildContext context, int index) { + final String? mime = lookupMimeType(_mediaFileList![index].path); + return Semantics( + label: 'image_picker_example_picked_image', + child: mime == null || mime.startsWith('image/') + ? Image.file( + File(_mediaFileList![index].path), + errorBuilder: (BuildContext context, Object error, + StackTrace? stackTrace) { + return const Center( + child: Text('This image type is not supported')); + }, + ) + : _buildInlineVideoPlayer(index), + ); + }, + itemCount: _mediaFileList!.length, + ), + ); + } else if (_pickImageError != null) { + return Text( + 'Pick image error: $_pickImageError', + textAlign: TextAlign.center, + ); + } else { + return const Text( + 'You have not yet picked an image.', + textAlign: TextAlign.center, + ); + } + } + + Widget _buildInlineVideoPlayer(int index) { + final VideoPlayerController controller = + VideoPlayerController.file(File(_mediaFileList![index].path)); + const double volume = 1.0; + controller.setVolume(volume); + controller.initialize(); + controller.setLooping(true); + controller.play(); + return Center(child: AspectRatioVideo(controller)); + } + + Widget _handlePreview() { + if (_isVideo) { + return _previewVideo(); + } else { + return _previewImages(); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title!), + ), + body: Center( + child: _handlePreview(), + ), + floatingActionButton: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Semantics( + label: 'image_picker_example_from_gallery', + child: FloatingActionButton( + key: const Key('image_picker_example_from_gallery'), + onPressed: () { + _isVideo = false; + _onImageButtonPressed(ImageSource.gallery, context: context); + }, + heroTag: 'image0', + tooltip: 'Pick Image from gallery', + child: const Icon(Icons.photo), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + onPressed: () { + _isVideo = false; + _onImageButtonPressed( + ImageSource.gallery, + context: context, + isMultiImage: true, + isMedia: true, + ); + }, + heroTag: 'multipleMedia', + tooltip: 'Pick Multiple Media from gallery', + child: const Icon(Icons.photo_library), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + onPressed: () { + _isVideo = false; + _onImageButtonPressed( + ImageSource.gallery, + context: context, + isMedia: true, + ); + }, + heroTag: 'media', + tooltip: 'Pick Single Media from gallery', + child: const Icon(Icons.photo_library), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + onPressed: () { + _isVideo = false; + _onImageButtonPressed( + ImageSource.gallery, + context: context, + isMultiImage: true, + ); + }, + heroTag: 'image1', + tooltip: 'Pick Multiple Image from gallery', + child: const Icon(Icons.photo_library), + ), + ), + if (_picker.supportsImageSource(ImageSource.camera)) + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + onPressed: () { + _isVideo = false; + _onImageButtonPressed(ImageSource.camera, context: context); + }, + heroTag: 'image2', + tooltip: 'Take a Photo', + child: const Icon(Icons.camera_alt), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + backgroundColor: Colors.red, + onPressed: () { + _isVideo = true; + _onImageButtonPressed(ImageSource.gallery, context: context); + }, + heroTag: 'video0', + tooltip: 'Pick Video from gallery', + child: const Icon(Icons.video_library), + ), + ), + if (_picker.supportsImageSource(ImageSource.camera)) + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + backgroundColor: Colors.red, + onPressed: () { + _isVideo = true; + _onImageButtonPressed(ImageSource.camera, context: context); + }, + heroTag: 'video1', + tooltip: 'Take a Video', + child: const Icon(Icons.videocam), + ), + ), + ], + ), + ); + } + + Text? _getRetrieveErrorWidget() { + if (_retrieveDataError != null) { + final Text result = Text(_retrieveDataError!); + _retrieveDataError = null; + return result; + } + return null; + } + + Future _displayPickImageDialog( + BuildContext context, OnPickImageCallback onPick) async { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Add optional parameters'), + content: Column( + children: [ + TextField( + controller: maxWidthController, + keyboardType: + const TextInputType.numberWithOptions(decimal: true), + decoration: const InputDecoration( + hintText: 'Enter maxWidth if desired'), + ), + TextField( + controller: maxHeightController, + keyboardType: + const TextInputType.numberWithOptions(decimal: true), + decoration: const InputDecoration( + hintText: 'Enter maxHeight if desired'), + ), + TextField( + controller: qualityController, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + hintText: 'Enter quality if desired'), + ), + ], + ), + actions: [ + TextButton( + child: const Text('CANCEL'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: const Text('PICK'), + onPressed: () { + final double? width = maxWidthController.text.isNotEmpty + ? double.parse(maxWidthController.text) + : null; + final double? height = maxHeightController.text.isNotEmpty + ? double.parse(maxHeightController.text) + : null; + final int? quality = qualityController.text.isNotEmpty + ? int.parse(qualityController.text) + : null; + onPick(width, height, quality); + Navigator.of(context).pop(); + }), + ], + ); + }); + } +} + +typedef OnPickImageCallback = void Function( + double? maxWidth, double? maxHeight, int? quality); + +class AspectRatioVideo extends StatefulWidget { + const AspectRatioVideo(this.controller, {super.key}); + + final VideoPlayerController? controller; + + @override + AspectRatioVideoState createState() => AspectRatioVideoState(); +} + +class AspectRatioVideoState extends State { + VideoPlayerController? get controller => widget.controller; + bool initialized = false; + + void _onVideoControllerUpdate() { + if (!mounted) { + return; + } + if (initialized != controller!.value.isInitialized) { + initialized = controller!.value.isInitialized; + setState(() {}); + } + } + + @override + void initState() { + super.initState(); + controller!.addListener(_onVideoControllerUpdate); + } + + @override + void dispose() { + controller!.removeListener(_onVideoControllerUpdate); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (initialized) { + return Center( + child: AspectRatio( + aspectRatio: controller!.value.aspectRatio, + child: VideoPlayer(controller!), + ), + ); + } else { + return Container(); + } + } +} + +T? _firstOrNull(List list) { + return list.isEmpty ? null : list.first; +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/CMakeLists.txt new file mode 100755 index 00000000..1fbfa727 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/CMakeLists.txt @@ -0,0 +1,138 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "example") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "dev.flutter.plugins.imagePickerExample") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# not the value here, or `flutter run` will no longer work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..d5bd0164 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/flutter/generated_plugins.cmake b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/flutter/generated_plugins.cmake new file mode 100755 index 00000000..2db3c22a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/main.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/main.cc new file mode 100755 index 00000000..1507d028 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/main.cc @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/my_application.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/my_application.cc new file mode 100755 index 00000000..3a67810f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/my_application.cc @@ -0,0 +1,111 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments( + project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, + gchar*** arguments, + int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = + my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, "flags", + G_APPLICATION_NON_UNIQUE, nullptr)); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/my_application.h b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/my_application.h new file mode 100755 index 00000000..6e9f0c3f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/linux/my_application.h @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/pubspec.yaml new file mode 100755 index 00000000..30f2d208 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/example/pubspec.yaml @@ -0,0 +1,29 @@ +name: example +description: Example for image_picker_linux implementation. +publish_to: 'none' +version: 1.0.0 + +environment: + sdk: ^3.4.0 + flutter: ">=3.22.0" + +dependencies: + flutter: + sdk: flutter + image_picker_linux: + # When depending on this package from a real application you should use: + # image_picker_linux: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: .. + image_picker_platform_interface: ^2.8.0 + mime: ^2.0.0 + video_player: ^2.1.4 + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/lib/image_picker_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/lib/image_picker_linux.dart new file mode 100755 index 00000000..20733898 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/lib/image_picker_linux.dart @@ -0,0 +1,182 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_linux/file_selector_linux.dart'; +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/foundation.dart'; +import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; + +/// The Linux implementation of [ImagePickerPlatform]. +/// +/// This class implements the `package:image_picker` functionality for +/// Linux. +class ImagePickerLinux extends CameraDelegatingImagePickerPlatform { + /// Constructs a platform implementation. + ImagePickerLinux(); + + /// The file selector used to prompt the user to select images or videos. + @visibleForTesting + static FileSelectorPlatform fileSelector = FileSelectorLinux(); + + /// Registers this class as the default instance of [ImagePickerPlatform]. + static void registerWith() { + ImagePickerPlatform.instance = ImagePickerLinux(); + } + + // This is soft-deprecated in the platform interface, and is only implemented + // for compatibility. Callers should be using getImageFromSource. + @override + Future pickImage({ + required ImageSource source, + double? maxWidth, + double? maxHeight, + int? imageQuality, + CameraDevice preferredCameraDevice = CameraDevice.rear, + }) async { + final XFile? file = await getImageFromSource( + source: source, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice)); + if (file != null) { + return PickedFile(file.path); + } + return null; + } + + // This is soft-deprecated in the platform interface, and is only implemented + // for compatibility. Callers should be using getVideo. + @override + Future pickVideo({ + required ImageSource source, + CameraDevice preferredCameraDevice = CameraDevice.rear, + Duration? maxDuration, + }) async { + final XFile? file = await getVideo( + source: source, + preferredCameraDevice: preferredCameraDevice, + maxDuration: maxDuration); + if (file != null) { + return PickedFile(file.path); + } + return null; + } + + // This is soft-deprecated in the platform interface, and is only implemented + // for compatibility. Callers should be using getImageFromSource. + @override + Future getImage({ + required ImageSource source, + double? maxWidth, + double? maxHeight, + int? imageQuality, + CameraDevice preferredCameraDevice = CameraDevice.rear, + }) async { + return getImageFromSource( + source: source, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice)); + } + + // [ImagePickerOptions] options are not currently supported. If any + // of its fields are set, they will be silently ignored. + // + // If source is `ImageSource.camera`, a `StateError` will be thrown + // unless a [cameraDelegate] is set. + @override + Future getImageFromSource({ + required ImageSource source, + ImagePickerOptions options = const ImagePickerOptions(), + }) async { + switch (source) { + case ImageSource.camera: + return super.getImageFromSource(source: source); + case ImageSource.gallery: + const XTypeGroup typeGroup = + XTypeGroup(label: 'Images', mimeTypes: ['image/*']); + final XFile? file = await fileSelector + .openFile(acceptedTypeGroups: [typeGroup]); + return file; + } + // Ensure that there's a fallback in case a new source is added. + // ignore: dead_code + throw UnimplementedError('Unknown ImageSource: $source'); + } + + // `preferredCameraDevice` and `maxDuration` arguments are not currently + // supported. If either of these arguments are supplied, they will be silently + // ignored. + // + // If source is `ImageSource.camera`, a `StateError` will be thrown + // unless a [cameraDelegate] is set. + @override + Future getVideo({ + required ImageSource source, + CameraDevice preferredCameraDevice = CameraDevice.rear, + Duration? maxDuration, + }) async { + switch (source) { + case ImageSource.camera: + return super.getVideo( + source: source, + preferredCameraDevice: preferredCameraDevice, + maxDuration: maxDuration); + case ImageSource.gallery: + const XTypeGroup typeGroup = + XTypeGroup(label: 'Videos', mimeTypes: ['video/*']); + final XFile? file = await fileSelector + .openFile(acceptedTypeGroups: [typeGroup]); + return file; + } + // Ensure that there's a fallback in case a new source is added. + // ignore: dead_code + throw UnimplementedError('Unknown ImageSource: $source'); + } + + // `maxWidth`, `maxHeight`, and `imageQuality` arguments are not currently + // supported. If any of these arguments are supplied, they will be silently + // ignored. + @override + Future> getMultiImage({ + double? maxWidth, + double? maxHeight, + int? imageQuality, + }) async { + const XTypeGroup typeGroup = + XTypeGroup(label: 'Images', mimeTypes: ['image/*']); + final List files = await fileSelector + .openFiles(acceptedTypeGroups: [typeGroup]); + return files; + } + + // `maxWidth`, `maxHeight`, and `imageQuality` arguments are not currently + // supported. If any of these arguments are supplied, they will be silently + // ignored. + @override + Future> getMedia({required MediaOptions options}) async { + const XTypeGroup typeGroup = XTypeGroup( + label: 'Images and videos', + mimeTypes: ['image/*', 'video/*'], + ); + + List files; + + if (options.allowMultiple) { + files = await fileSelector + .openFiles(acceptedTypeGroups: [typeGroup]); + } else { + final XFile? file = await fileSelector + .openFile(acceptedTypeGroups: [typeGroup]); + files = [ + if (file != null) file, + ]; + } + return files; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/pubspec.yaml new file mode 100755 index 00000000..c7b84ec1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/pubspec.yaml @@ -0,0 +1,34 @@ +name: image_picker_linux +description: Linux platform implementation of image_picker +repository: https://github.com/flutter/packages/tree/main/packages/image_picker/image_picker_linux +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 +version: 0.2.1+2 + +environment: + sdk: ^3.4.0 + flutter: ">=3.22.0" + +flutter: + plugin: + implements: image_picker + platforms: + linux: + dartPluginClass: ImagePickerLinux + +dependencies: + file_selector_linux: ^0.9.1+3 + file_selector_platform_interface: ^2.2.0 + flutter: + sdk: flutter + image_picker_platform_interface: ^2.8.0 + +dev_dependencies: + build_runner: ^2.1.5 + flutter_test: + sdk: flutter + mockito: ^5.4.4 + +topics: + - image-picker + - files + - file-selection diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/test/image_picker_linux_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/test/image_picker_linux_test.dart new file mode 100755 index 00000000..b8a92eef --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/test/image_picker_linux_test.dart @@ -0,0 +1,180 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:image_picker_linux/image_picker_linux.dart'; +import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'image_picker_linux_test.mocks.dart'; + +@GenerateMocks([FileSelectorPlatform]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + // Returns the captured type groups from a mock call result, assuming that + // exactly one call was made and only the type groups were captured. + List capturedTypeGroups(VerificationResult result) { + return result.captured.single as List; + } + + late ImagePickerLinux plugin; + late MockFileSelectorPlatform mockFileSelectorPlatform; + + setUp(() { + plugin = ImagePickerLinux(); + mockFileSelectorPlatform = MockFileSelectorPlatform(); + + when(mockFileSelectorPlatform.openFile( + acceptedTypeGroups: anyNamed('acceptedTypeGroups'))) + .thenAnswer((_) async => null); + + when(mockFileSelectorPlatform.openFiles( + acceptedTypeGroups: anyNamed('acceptedTypeGroups'))) + .thenAnswer((_) async => List.empty()); + + ImagePickerLinux.fileSelector = mockFileSelectorPlatform; + }); + + test('registered instance', () { + ImagePickerLinux.registerWith(); + expect(ImagePickerPlatform.instance, isA()); + }); + + group('images', () { + test('pickImage passes the accepted type groups correctly', () async { + await plugin.pickImage(source: ImageSource.gallery); + + final VerificationResult result = verify(mockFileSelectorPlatform + .openFile(acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].mimeTypes, ['image/*']); + }); + + test('getImage passes the accepted type groups correctly', () async { + await plugin.getImage(source: ImageSource.gallery); + + final VerificationResult result = verify(mockFileSelectorPlatform + .openFile(acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].mimeTypes, ['image/*']); + }); + + test('getImageFromSource passes the accepted type groups correctly', + () async { + await plugin.getImageFromSource(source: ImageSource.gallery); + + final VerificationResult result = verify(mockFileSelectorPlatform + .openFile(acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].mimeTypes, ['image/*']); + }); + + test('getImageFromSource calls delegate when source is camera', () async { + const String fakePath = '/tmp/foo'; + plugin.cameraDelegate = FakeCameraDelegate(result: XFile(fakePath)); + expect( + (await plugin.getImageFromSource(source: ImageSource.camera))!.path, + fakePath); + }); + + test( + 'getImageFromSource throws StateError when source is camera with no delegate', + () async { + await expectLater(plugin.getImageFromSource(source: ImageSource.camera), + throwsStateError); + }); + + test('getMultiImage passes the accepted type groups correctly', () async { + await plugin.getMultiImage(); + + final VerificationResult result = verify( + mockFileSelectorPlatform.openFiles( + acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].mimeTypes, ['image/*']); + }); + }); + + group('videos', () { + test('pickVideo passes the accepted type groups correctly', () async { + await plugin.pickVideo(source: ImageSource.gallery); + + final VerificationResult result = verify(mockFileSelectorPlatform + .openFile(acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].mimeTypes, ['video/*']); + }); + + test('getVideo passes the accepted type groups correctly', () async { + await plugin.getVideo(source: ImageSource.gallery); + + final VerificationResult result = verify(mockFileSelectorPlatform + .openFile(acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].mimeTypes, ['video/*']); + }); + + test('getVideo calls delegate when source is camera', () async { + const String fakePath = '/tmp/foo'; + plugin.cameraDelegate = FakeCameraDelegate(result: XFile(fakePath)); + expect( + (await plugin.getVideo(source: ImageSource.camera))!.path, fakePath); + }); + + test('getVideo throws StateError when source is camera with no delegate', + () async { + await expectLater( + plugin.getVideo(source: ImageSource.camera), throwsStateError); + }); + }); + + group('media', () { + test('getMedia passes the accepted type groups correctly', () async { + await plugin.getMedia(options: const MediaOptions(allowMultiple: true)); + + final VerificationResult result = verify( + mockFileSelectorPlatform.openFiles( + acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].mimeTypes, + ['image/*', 'video/*']); + }); + + test('multiple media handles an empty path response gracefully', () async { + expect( + await plugin.getMedia( + options: const MediaOptions( + allowMultiple: true, + ), + ), + []); + }); + + test('single media handles an empty path response gracefully', () async { + expect( + await plugin.getMedia( + options: const MediaOptions( + allowMultiple: false, + ), + ), + []); + }); + }); +} + +class FakeCameraDelegate extends ImagePickerCameraDelegate { + FakeCameraDelegate({this.result}); + + XFile? result; + + @override + Future takePhoto( + {ImagePickerCameraDelegateOptions options = + const ImagePickerCameraDelegateOptions()}) async { + return result; + } + + @override + Future takeVideo( + {ImagePickerCameraDelegateOptions options = + const ImagePickerCameraDelegateOptions()}) async { + return result; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/test/image_picker_linux_test.mocks.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/test/image_picker_linux_test.mocks.dart new file mode 100755 index 00000000..5980f991 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/image_picker_linux/test/image_picker_linux_test.mocks.dart @@ -0,0 +1,143 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in image_picker_linux/test/image_picker_linux_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart' + as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +/// A class which mocks [FileSelectorPlatform]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFileSelectorPlatform extends _i1.Mock + implements _i2.FileSelectorPlatform { + MockFileSelectorPlatform() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future<_i2.XFile?> openFile({ + List<_i2.XTypeGroup>? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #openFile, + [], + { + #acceptedTypeGroups: acceptedTypeGroups, + #initialDirectory: initialDirectory, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future<_i2.XFile?>.value(), + ) as _i3.Future<_i2.XFile?>); + + @override + _i3.Future> openFiles({ + List<_i2.XTypeGroup>? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #openFiles, + [], + { + #acceptedTypeGroups: acceptedTypeGroups, + #initialDirectory: initialDirectory, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future>.value(<_i2.XFile>[]), + ) as _i3.Future>); + + @override + _i3.Future getSavePath({ + List<_i2.XTypeGroup>? acceptedTypeGroups, + String? initialDirectory, + String? suggestedName, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #getSavePath, + [], + { + #acceptedTypeGroups: acceptedTypeGroups, + #initialDirectory: initialDirectory, + #suggestedName: suggestedName, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future<_i2.FileSaveLocation?> getSaveLocation({ + List<_i2.XTypeGroup>? acceptedTypeGroups, + _i2.SaveDialogOptions? options = const _i2.SaveDialogOptions(), + }) => + (super.noSuchMethod( + Invocation.method( + #getSaveLocation, + [], + { + #acceptedTypeGroups: acceptedTypeGroups, + #options: options, + }, + ), + returnValue: _i3.Future<_i2.FileSaveLocation?>.value(), + ) as _i3.Future<_i2.FileSaveLocation?>); + + @override + _i3.Future getDirectoryPath({ + String? initialDirectory, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #getDirectoryPath, + [], + { + #initialDirectory: initialDirectory, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + + @override + _i3.Future> getDirectoryPaths({ + String? initialDirectory, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #getDirectoryPaths, + [], + { + #initialDirectory: initialDirectory, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future>.value([]), + ) as _i3.Future>); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux deleted file mode 120000 index 263d8799..00000000 --- a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/AUTHORS b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/AUTHORS new file mode 100755 index 00000000..493a0b4e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/AUTHORS @@ -0,0 +1,66 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. +The Chromium Authors +German Saprykin +Benjamin Sauer +larsenthomasj@gmail.com +Ali Bitek +Pol Batlló +Anatoly Pulyaevskiy +Hayden Flinner +Stefano Rodriguez +Salvatore Giordano +Brian Armstrong +Paul DeMarco +Fabricio Nogueira +Simon Lightfoot +Ashton Thomas +Thomas Danner +Diego Velásquez +Hajime Nakamura +Tuyển Vũ Xuân +Miguel Ruivo +Sarthak Verma +Mike Diarmid +Invertase +Elliot Hesp +Vince Varga +Aawaz Gyawali +EUI Limited +Katarina Sheremet +Thomas Stockx +Sarbagya Dhaubanjar +Ozkan Eksi +Rishab Nayak +ko2ic +Jonathan Younger +Jose Sanchez +Debkanchan Samadder +Audrius Karosevicius +Lukasz Piliszczuk +SoundReply Solutions GmbH +Rafal Wachol +Pau Picas +Christian Weder +Alexandru Tuca +Christian Weder +Rhodes Davis Jr. +Luigi Agosti +Quentin Le Guennec +Koushik Ravikumar +Nissim Dsilva +Giancarlo Rocha +Ryo Miyake +Théo Champion +Kazuki Yamaguchi +Eitan Schwartz +Chris Rutkowski +Juan Alvarez +Aleksandr Yurkovskiy +Anton Borries +Alex Li +Rahul Raj <64.rahulraj@gmail.com> diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/CHANGELOG.md b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/CHANGELOG.md new file mode 100755 index 00000000..ace2dad7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/CHANGELOG.md @@ -0,0 +1,109 @@ +## 2.2.1 + +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. + +## 2.2.0 + +* Adds getApplicationCachePath() for storing app-specific cache files. + +## 2.1.11 + +* Removes obsolete null checks on non-nullable values. +* Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. + +## 2.1.10 + +* Clarifies explanation of endorsement in README. +* Aligns Dart and Flutter SDK constraints. + +## 2.1.9 + +* Updates links for the merge of flutter/plugins into flutter/packages. + +## 2.1.8 + +* Adds compatibility with `xdg_directories` 1.0. +* Updates minimum Flutter version to 3.0. + +## 2.1.7 + +* Bumps ffi dependency to match path_provider_windows. + +## 2.1.6 + +* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors + lint warnings. + +## 2.1.5 + +* Removes dependency on `meta`. + +## 2.1.4 + +* Fixes `getApplicationSupportPath` handling of applications where the + application ID is not set. + +## 2.1.3 + +* Change getApplicationSupportPath from using executable name to application ID (if provided). + * If the executable name based directory exists, continue to use that so existing applications continue with the same behaviour. + +## 2.1.2 + +* Fixes link in README. + +## 2.1.1 + +* Removed obsolete `pluginClass: none` from pubpsec. + +## 2.1.0 + +* Now `getTemporaryPath` returns the value of the `TMPDIR` environment variable primarily. If `TMPDIR` is not set, `/tmp` is returned. + +## 2.0.2 + +* Updated installation instructions in README. + +## 2.0.1 + +* Add `implements` to pubspec.yaml. +* Add `registerWith` method to the main Dart class. + +## 2.0.0 + +* Migrate to null safety. + +## 0.1.1+3 + +* Update Flutter SDK constraint. + +## 0.1.1+2 + +* Log errors in the example when calls to the `path_provider` fail. + +## 0.1.1+1 + +* Check in linux/ directory for example/ + +## 0.1.1 - NOT PUBLISHED + +* Reverts changes on 0.1.0, which broke the tree. + +## 0.1.0 - NOT PUBLISHED + +* This release updates getApplicationSupportPath to use the application ID instead of the executable name. + * No migration is provided, so any older apps that were using this path will now have a different directory. + +## 0.0.1+2 + +* This release updates the example to depend on the endorsed plugin rather than relative path + +## 0.0.1+1 + +* This updates the readme and pubspec and example to reflect the endorsement of this implementation of `path_provider` + +## 0.0.1 + +* The initial implementation of path\_provider for Linux + * Implements getApplicationSupportPath, getApplicationDocumentsPath, getDownloadsPath, and getTemporaryPath diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/LICENSE b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/LICENSE new file mode 100755 index 00000000..c6823b81 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/README.md new file mode 100755 index 00000000..12c5c514 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/README.md @@ -0,0 +1,15 @@ +# path\_provider\_linux + +The linux implementation of [`path_provider`][1]. + +## Usage + +This package is [endorsed][2], which means you can simply use `path_provider` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. + +[1]: https://pub.dev/packages/path_provider +[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/README.md new file mode 100755 index 00000000..96b8bb17 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/integration_test/path_provider_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/integration_test/path_provider_test.dart new file mode 100755 index 00000000..3353f561 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/integration_test/path_provider_test.dart @@ -0,0 +1,66 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:path_provider_linux/path_provider_linux.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('getTemporaryDirectory', (WidgetTester tester) async { + final PathProviderLinux provider = PathProviderLinux(); + final String? result = await provider.getTemporaryPath(); + _verifySampleFile(result, 'temporaryDirectory'); + }); + + testWidgets('getDownloadDirectory', (WidgetTester tester) async { + if (!Platform.isLinux) { + return; + } + final PathProviderLinux provider = PathProviderLinux(); + final String? result = await provider.getDownloadsPath(); + _verifySampleFile(result, 'downloadDirectory'); + }); + + testWidgets('getApplicationDocumentsDirectory', (WidgetTester tester) async { + final PathProviderLinux provider = PathProviderLinux(); + final String? result = await provider.getApplicationDocumentsPath(); + _verifySampleFile(result, 'applicationDocuments'); + }); + + testWidgets('getApplicationSupportDirectory', (WidgetTester tester) async { + final PathProviderLinux provider = PathProviderLinux(); + final String? result = await provider.getApplicationSupportPath(); + _verifySampleFile(result, 'applicationSupport'); + }); + + testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async { + final PathProviderLinux provider = PathProviderLinux(); + final String? result = await provider.getApplicationCachePath(); + _verifySampleFile(result, 'applicationCache'); + }); +} + +/// Verify a file called [name] in [directoryPath] by recreating it with test +/// contents when necessary. +void _verifySampleFile(String? directoryPath, String name) { + expect(directoryPath, isNotNull); + if (directoryPath == null) { + return; + } + final Directory directory = Directory(directoryPath); + final File file = File('${directory.path}${Platform.pathSeparator}$name'); + + if (file.existsSync()) { + file.deleteSync(); + expect(file.existsSync(), isFalse); + } + + file.writeAsStringSync('Hello world!'); + expect(file.readAsStringSync(), 'Hello world!'); + expect(directory.listSync(), isNotEmpty); + file.deleteSync(); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/lib/main.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/lib/main.dart new file mode 100755 index 00000000..3cbb6915 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/lib/main.dart @@ -0,0 +1,109 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:path_provider_linux/path_provider_linux.dart'; + +void main() { + runApp(const MyApp()); +} + +/// Sample app +class MyApp extends StatefulWidget { + /// Default Constructor + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + String? _tempDirectory = 'Unknown'; + String? _downloadsDirectory = 'Unknown'; + String? _appSupportDirectory = 'Unknown'; + String? _appCacheDirectory = 'Unknown'; + String? _documentsDirectory = 'Unknown'; + final PathProviderLinux _provider = PathProviderLinux(); + + @override + void initState() { + super.initState(); + initDirectories(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future initDirectories() async { + String? tempDirectory; + String? downloadsDirectory; + String? appSupportDirectory; + String? appCacheDirectory; + String? documentsDirectory; + // Platform messages may fail, so we use a try/catch PlatformException. + try { + tempDirectory = await _provider.getTemporaryPath(); + } on PlatformException { + tempDirectory = 'Failed to get temp directory.'; + } + try { + downloadsDirectory = await _provider.getDownloadsPath(); + } on PlatformException { + downloadsDirectory = 'Failed to get downloads directory.'; + } + + try { + documentsDirectory = await _provider.getApplicationDocumentsPath(); + } on PlatformException { + documentsDirectory = 'Failed to get documents directory.'; + } + + try { + appSupportDirectory = await _provider.getApplicationSupportPath(); + } on PlatformException { + appSupportDirectory = 'Failed to get documents directory.'; + } + + try { + appCacheDirectory = await _provider.getApplicationCachePath(); + } on PlatformException { + appCacheDirectory = 'Failed to get cache directory.'; + } + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) { + return; + } + + setState(() { + _tempDirectory = tempDirectory; + _downloadsDirectory = downloadsDirectory; + _appSupportDirectory = appSupportDirectory; + _appCacheDirectory = appCacheDirectory; + _documentsDirectory = documentsDirectory; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Path Provider Linux example app'), + ), + body: Center( + child: Column( + children: [ + Text('Temp Directory: $_tempDirectory\n'), + Text('Documents Directory: $_documentsDirectory\n'), + Text('Downloads Directory: $_downloadsDirectory\n'), + Text('Application Support Directory: $_appSupportDirectory\n'), + Text('Application Cache Directory: $_appCacheDirectory\n'), + ], + ), + ), + ), + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/CMakeLists.txt new file mode 100755 index 00000000..4c422c77 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "dev.flutter.plugins.path_provider_linux_example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..94f43ff7 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,86 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + linux-x64 ${CMAKE_BUILD_TYPE} +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/flutter/generated_plugins.cmake b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/flutter/generated_plugins.cmake new file mode 100755 index 00000000..2e1de87a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/main.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/main.cc new file mode 100755 index 00000000..88a5fd45 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/main.cc @@ -0,0 +1,15 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +int main(int argc, char** argv) { + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); + + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/my_application.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/my_application.cc new file mode 100755 index 00000000..9cb411ba --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/my_application.cc @@ -0,0 +1,49 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/my_application.h b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/my_application.h new file mode 100755 index 00000000..6e9f0c3f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/linux/my_application.h @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/pubspec.yaml new file mode 100755 index 00000000..33fa8914 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/pubspec.yaml @@ -0,0 +1,28 @@ +name: pathproviderexample +description: Demonstrates how to use the path_provider_linux plugin. +publish_to: "none" + +environment: + sdk: ">=2.19.0 <4.0.0" + flutter: ">=3.7.0" + +dependencies: + flutter: + sdk: flutter + + path_provider_linux: + # When depending on this package from a real application you should use: + # path_provider_linux: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/test_driver/integration_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/test_driver/integration_test.dart new file mode 100755 index 00000000..4f10f2a5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/path_provider_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/path_provider_linux.dart new file mode 100755 index 00000000..e32af1bf --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/path_provider_linux.dart @@ -0,0 +1,5 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export 'src/path_provider_linux.dart'; diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/get_application_id.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/get_application_id.dart new file mode 100755 index 00000000..e169c025 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/get_application_id.dart @@ -0,0 +1,9 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// getApplicationId() is implemented using FFI; export a stub for platforms +// that don't support FFI (e.g., web) to avoid having transitive dependencies +// break web compilation. +export 'get_application_id_stub.dart' + if (dart.library.ffi) 'get_application_id_real.dart'; diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/get_application_id_real.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/get_application_id_real.dart new file mode 100755 index 00000000..5e16df06 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/get_application_id_real.dart @@ -0,0 +1,78 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ffi'; +import 'package:ffi/ffi.dart'; +import 'package:flutter/foundation.dart' show visibleForTesting; + +// GApplication* g_application_get_default(); +typedef _GApplicationGetDefaultC = IntPtr Function(); +typedef _GApplicationGetDefaultDart = int Function(); + +// const gchar* g_application_get_application_id(GApplication* application); +typedef _GApplicationGetApplicationIdC = Pointer Function(IntPtr); +typedef _GApplicationGetApplicationIdDart = Pointer Function(int); + +/// Interface for interacting with libgio. +@visibleForTesting +class GioUtils { + /// Creates a default instance that uses the real libgio. + GioUtils() { + try { + _gio = DynamicLibrary.open('libgio-2.0.so'); + } on ArgumentError { + _gio = null; + } + } + + DynamicLibrary? _gio; + + /// True if libgio was opened successfully. + bool get libraryIsPresent => _gio != null; + + /// Wraps `g_application_get_default`. + int gApplicationGetDefault() { + if (_gio == null) { + return 0; + } + final _GApplicationGetDefaultDart getDefault = _gio! + .lookupFunction<_GApplicationGetDefaultC, _GApplicationGetDefaultDart>( + 'g_application_get_default'); + return getDefault(); + } + + /// Wraps g_application_get_application_id. + Pointer gApplicationGetApplicationId(int app) { + if (_gio == null) { + return nullptr; + } + final _GApplicationGetApplicationIdDart gApplicationGetApplicationId = _gio! + .lookupFunction<_GApplicationGetApplicationIdC, + _GApplicationGetApplicationIdDart>( + 'g_application_get_application_id'); + return gApplicationGetApplicationId(app); + } +} + +/// Allows overriding the default GioUtils instance with a fake for testing. +@visibleForTesting +GioUtils? gioUtilsOverride; + +/// Gets the application ID for this app. +String? getApplicationId() { + final GioUtils gio = gioUtilsOverride ?? GioUtils(); + if (!gio.libraryIsPresent) { + return null; + } + + final int app = gio.gApplicationGetDefault(); + if (app == 0) { + return null; + } + final Pointer appId = gio.gApplicationGetApplicationId(app); + if (appId == nullptr) { + return null; + } + return appId.toDartString(); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/get_application_id_stub.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/get_application_id_stub.dart new file mode 100755 index 00000000..90999769 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/get_application_id_stub.dart @@ -0,0 +1,6 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Gets the application ID for this app. +String? getApplicationId() => null; diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/path_provider_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/path_provider_linux.dart new file mode 100755 index 00000000..59097114 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/lib/src/path_provider_linux.dart @@ -0,0 +1,102 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; +import 'package:xdg_directories/xdg_directories.dart' as xdg; + +import 'get_application_id.dart'; + +/// The linux implementation of [PathProviderPlatform] +/// +/// This class implements the `package:path_provider` functionality for Linux. +class PathProviderLinux extends PathProviderPlatform { + /// Constructs an instance of [PathProviderLinux] + PathProviderLinux() : _environment = Platform.environment; + + /// Constructs an instance of [PathProviderLinux] with the given [environment] + @visibleForTesting + PathProviderLinux.private( + {Map environment = const {}, + String? executableName, + String? applicationId}) + : _environment = environment, + _executableName = executableName, + _applicationId = applicationId; + + final Map _environment; + String? _executableName; + String? _applicationId; + + /// Registers this class as the default instance of [PathProviderPlatform] + static void registerWith() { + PathProviderPlatform.instance = PathProviderLinux(); + } + + @override + Future getTemporaryPath() { + final String environmentTmpDir = _environment['TMPDIR'] ?? ''; + return Future.value( + environmentTmpDir.isEmpty ? '/tmp' : environmentTmpDir, + ); + } + + @override + Future getApplicationSupportPath() async { + final Directory directory = + Directory(path.join(xdg.dataHome.path, await _getId())); + if (directory.existsSync()) { + return directory.path; + } + + // This plugin originally used the executable name as a directory. + // Use that if it exists for backwards compatibility. + final Directory legacyDirectory = + Directory(path.join(xdg.dataHome.path, await _getExecutableName())); + if (legacyDirectory.existsSync()) { + return legacyDirectory.path; + } + + // Create the directory, because mobile implementations assume the directory exists. + await directory.create(recursive: true); + return directory.path; + } + + @override + Future getApplicationDocumentsPath() { + return Future.value(xdg.getUserDirectory('DOCUMENTS')?.path); + } + + @override + Future getApplicationCachePath() async { + final Directory directory = + Directory(path.join(xdg.cacheHome.path, await _getId())); + if (!directory.existsSync()) { + await directory.create(recursive: true); + } + return directory.path; + } + + @override + Future getDownloadsPath() { + return Future.value(xdg.getUserDirectory('DOWNLOAD')?.path); + } + + // Gets the name of this executable. + Future _getExecutableName() async { + _executableName ??= path.basenameWithoutExtension( + await File('/proc/self/exe').resolveSymbolicLinks()); + return _executableName!; + } + + // Gets the unique ID for this application. + Future _getId() async { + _applicationId ??= getApplicationId(); + // If no application ID then fall back to using the executable name. + return _applicationId ?? await _getExecutableName(); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/pubspec.yaml new file mode 100755 index 00000000..4ad2805a --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/pubspec.yaml @@ -0,0 +1,33 @@ +name: path_provider_linux +description: Linux implementation of the path_provider plugin +repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_linux +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 +version: 2.2.1 + +environment: + sdk: ">=2.19.0 <4.0.0" + flutter: ">=3.7.0" + +flutter: + plugin: + implements: path_provider + platforms: + linux: + dartPluginClass: PathProviderLinux + +dependencies: + ffi: ">=1.1.2 <3.0.0" + flutter: + sdk: flutter + path: ^1.8.0 + path_provider_platform_interface: ^2.1.0 + xdg_directories: ">=0.2.0 <2.0.0" + +dev_dependencies: + flutter_test: + sdk: flutter + +topics: + - files + - path-provider + - paths diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/test/get_application_id_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/test/get_application_id_test.dart new file mode 100755 index 00000000..d9eb5163 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/test/get_application_id_test.dart @@ -0,0 +1,62 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path_provider_linux/src/get_application_id_real.dart'; + +class _FakeGioUtils implements GioUtils { + int? application; + Pointer? applicationId; + + @override + bool libraryIsPresent = false; + + @override + int gApplicationGetDefault() => application!; + + @override + Pointer gApplicationGetApplicationId(int app) => applicationId!; +} + +void main() { + late _FakeGioUtils fakeGio; + + setUp(() { + fakeGio = _FakeGioUtils(); + gioUtilsOverride = fakeGio; + }); + + tearDown(() { + gioUtilsOverride = null; + }); + + test('returns null if libgio is not available', () { + expect(getApplicationId(), null); + }); + + test('returns null if g_paplication_get_default returns 0', () { + fakeGio.libraryIsPresent = true; + fakeGio.application = 0; + expect(getApplicationId(), null); + }); + + test('returns null if g_application_get_application_id returns nullptr', () { + fakeGio.libraryIsPresent = true; + fakeGio.application = 1; + fakeGio.applicationId = nullptr; + expect(getApplicationId(), null); + }); + + test('returns value if g_application_get_application_id returns a value', () { + fakeGio.libraryIsPresent = true; + fakeGio.application = 1; + const String id = 'foo'; + final Pointer idPtr = id.toNativeUtf8(); + fakeGio.applicationId = idPtr; + expect(getApplicationId(), id); + calloc.free(idPtr); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/test/path_provider_linux_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/test/path_provider_linux_test.dart new file mode 100755 index 00000000..b5dfcce1 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/path_provider_linux/test/path_provider_linux_test.dart @@ -0,0 +1,71 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'package:flutter_test/flutter_test.dart'; +import 'package:path_provider_linux/path_provider_linux.dart'; +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; +import 'package:xdg_directories/xdg_directories.dart' as xdg; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + PathProviderLinux.registerWith(); + + test('registered instance', () { + expect(PathProviderPlatform.instance, isA()); + }); + + test('getTemporaryPath defaults to TMPDIR', () async { + final PathProviderPlatform plugin = PathProviderLinux.private( + environment: {'TMPDIR': '/run/user/0/tmp'}, + ); + expect(await plugin.getTemporaryPath(), '/run/user/0/tmp'); + }); + + test('getTemporaryPath uses fallback if TMPDIR is empty', () async { + final PathProviderPlatform plugin = PathProviderLinux.private( + environment: {'TMPDIR': ''}, + ); + expect(await plugin.getTemporaryPath(), '/tmp'); + }); + + test('getTemporaryPath uses fallback if TMPDIR is unset', () async { + final PathProviderPlatform plugin = PathProviderLinux.private( + environment: {}, + ); + expect(await plugin.getTemporaryPath(), '/tmp'); + }); + + test('getApplicationSupportPath', () async { + final PathProviderPlatform plugin = PathProviderLinux.private( + executableName: 'path_provider_linux_test_binary', + applicationId: 'com.example.Test'); + // Note this will fail if ${xdg.dataHome.path}/path_provider_linux_test_binary exists on the local filesystem. + expect(await plugin.getApplicationSupportPath(), + '${xdg.dataHome.path}/com.example.Test'); + }); + + test('getApplicationSupportPath uses executable name if no application Id', + () async { + final PathProviderPlatform plugin = PathProviderLinux.private( + executableName: 'path_provider_linux_test_binary'); + expect(await plugin.getApplicationSupportPath(), + '${xdg.dataHome.path}/path_provider_linux_test_binary'); + }); + + test('getApplicationDocumentsPath', () async { + final PathProviderPlatform plugin = PathProviderPlatform.instance; + expect(await plugin.getApplicationDocumentsPath(), startsWith('/')); + }); + + test('getApplicationCachePath', () async { + final PathProviderPlatform plugin = PathProviderLinux.private( + executableName: 'path_provider_linux_test_binary'); + expect(await plugin.getApplicationCachePath(), + '${xdg.cacheHome.path}/path_provider_linux_test_binary'); + }); + + test('getDownloadsPath', () async { + final PathProviderPlatform plugin = PathProviderPlatform.instance; + expect(await plugin.getDownloadsPath(), startsWith('/')); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux deleted file mode 120000 index aadcdac4..00000000 --- a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/ \ No newline at end of file diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/AUTHORS b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/AUTHORS new file mode 100755 index 00000000..493a0b4e --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/AUTHORS @@ -0,0 +1,66 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. +The Chromium Authors +German Saprykin +Benjamin Sauer +larsenthomasj@gmail.com +Ali Bitek +Pol Batlló +Anatoly Pulyaevskiy +Hayden Flinner +Stefano Rodriguez +Salvatore Giordano +Brian Armstrong +Paul DeMarco +Fabricio Nogueira +Simon Lightfoot +Ashton Thomas +Thomas Danner +Diego Velásquez +Hajime Nakamura +Tuyển Vũ Xuân +Miguel Ruivo +Sarthak Verma +Mike Diarmid +Invertase +Elliot Hesp +Vince Varga +Aawaz Gyawali +EUI Limited +Katarina Sheremet +Thomas Stockx +Sarbagya Dhaubanjar +Ozkan Eksi +Rishab Nayak +ko2ic +Jonathan Younger +Jose Sanchez +Debkanchan Samadder +Audrius Karosevicius +Lukasz Piliszczuk +SoundReply Solutions GmbH +Rafal Wachol +Pau Picas +Christian Weder +Alexandru Tuca +Christian Weder +Rhodes Davis Jr. +Luigi Agosti +Quentin Le Guennec +Koushik Ravikumar +Nissim Dsilva +Giancarlo Rocha +Ryo Miyake +Théo Champion +Kazuki Yamaguchi +Eitan Schwartz +Chris Rutkowski +Juan Alvarez +Aleksandr Yurkovskiy +Anton Borries +Alex Li +Rahul Raj <64.rahulraj@gmail.com> diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/CHANGELOG.md b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/CHANGELOG.md new file mode 100755 index 00000000..7ba11785 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/CHANGELOG.md @@ -0,0 +1,105 @@ +## 3.2.1 + +* Updates Pigeon to resolve a compilation failure with some versions of glib. + +## 3.2.0 + +* Updates platform channels to use Pigeon. +* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. + +## 3.1.1 + +* Implements `launchUrl`. +* Simplifies method channel interface by removing unused elements. +* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0. + +## 3.1.0 + +* Implements `supportsMode` and `supportsCloseForMode`. + +## 3.0.6 + +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. + +## 3.0.5 + +* Sets a cmake_policy compatibility version to fix build warnings. + +## 3.0.4 + +* Clarifies explanation of endorsement in README. +* Aligns Dart and Flutter SDK constraints. + +## 3.0.3 + +* Updates links for the merge of flutter/plugins into flutter/packages. +* Updates minimum Flutter version to 3.0. + +## 3.0.2 + +* Updates code for stricter lint checks. +* Updates minimum Flutter version to 2.10. + +## 3.0.1 + +* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors + lint warnings. + +## 3.0.0 + +* Changes the major version since, due to a typo in `default_package` in + existing versions of `url_launcher`, requiring Dart registration in this + package is in practice a breaking change. + * Does not include any API changes; clients can allow both 2.x or 3.x. + +## 2.0.4 + +* **\[Retracted\]** Switches to an in-package method channel implementation. + +## 2.0.3 + +* Updates code for new analysis options. +* Fix minor memory leak in Linux url_launcher tests. +* Fixes canLaunch detection for URIs addressing on local or network file systems + +## 2.0.2 + +* Replaced reference to `shared_preferences` plugin with the `url_launcher` in the README. + +## 2.0.1 + +* Updated installation instructions in README. + +## 2.0.0 + +* Migrate to null safety. +* Update the example app: remove the deprecated `RaisedButton` and `FlatButton` widgets. +* Fix outdated links across a number of markdown files ([#3276](https://github.com/flutter/plugins/pull/3276)) +* Set `implementation` in pubspec.yaml + +## 0.0.2+1 + +* Update Flutter SDK constraint. + +## 0.0.2 + +* Update integration test examples to use `testWidgets` instead of `test`. + +## 0.0.1+4 + +* Update Dart SDK constraint in example. + +## 0.0.1+3 + +* Add a missing include. + +## 0.0.1+2 + +* Check in linux/ directory for example/ + +# 0.0.1+1 +* README update for endorsement by url_launcher. + +# 0.0.1 +* The initial implementation of url_launcher for Linux diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/LICENSE b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/LICENSE new file mode 100755 index 00000000..c6823b81 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/README.md new file mode 100755 index 00000000..143e1f36 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/README.md @@ -0,0 +1,15 @@ +# url\_launcher\_linux + +The Linux implementation of [`url_launcher`][1]. + +## Usage + +This package is [endorsed][2], which means you can simply use `url_launcher` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. + +[1]: https://pub.dev/packages/url_launcher +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/README.md b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/README.md new file mode 100755 index 00000000..96b8bb17 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/integration_test/url_launcher_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/integration_test/url_launcher_test.dart new file mode 100755 index 00000000..c9d0d8c9 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/integration_test/url_launcher_test.dart @@ -0,0 +1,20 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('canLaunch', (WidgetTester _) async { + final UrlLauncherPlatform launcher = UrlLauncherPlatform.instance; + + expect(await launcher.canLaunch('randomstring'), false); + + // Generally all devices should have some default browser. + expect(await launcher.canLaunch('http://flutter.dev'), true); + }); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/lib/main.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/lib/main.dart new file mode 100755 index 00000000..739d09d0 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/lib/main.dart @@ -0,0 +1,95 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'URL Launcher', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: const MyHomePage(title: 'URL Launcher'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + Future? _launched; + + Future _launchInBrowser(String url) async { + if (await UrlLauncherPlatform.instance.canLaunch(url)) { + await UrlLauncherPlatform.instance.launch( + url, + useSafariVC: false, + useWebView: false, + enableJavaScript: false, + enableDomStorage: false, + universalLinksOnly: false, + headers: {}, + ); + } else { + throw Exception('Could not launch $url'); + } + } + + Widget _launchStatus(BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else { + return const Text(''); + } + } + + @override + Widget build(BuildContext context) { + const String toLaunch = 'https://www.cylog.org/headers/'; + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: ListView( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Padding( + padding: EdgeInsets.all(16.0), + child: Text(toLaunch), + ), + ElevatedButton( + onPressed: () => setState(() { + _launched = _launchInBrowser(toLaunch); + }), + child: const Text('Launch in browser'), + ), + const Padding(padding: EdgeInsets.all(16.0)), + FutureBuilder(future: _launched, builder: _launchStatus), + ], + ), + ], + ), + ); + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/CMakeLists.txt new file mode 100755 index 00000000..11219aa5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/CMakeLists.txt @@ -0,0 +1,100 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Enable the test target. +set(include_url_launcher_linux_tests TRUE) +# Provide an alias for the test target using the name expected by repo tooling. +add_custom_target(unit_tests DEPENDS url_launcher_linux_test) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/flutter/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..33fd5801 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,87 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/flutter/generated_plugins.cmake b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/flutter/generated_plugins.cmake new file mode 100755 index 00000000..f16b4c34 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/main.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/main.cc new file mode 100755 index 00000000..1507d028 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/main.cc @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/my_application.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/my_application.cc new file mode 100755 index 00000000..878cd973 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/my_application.cc @@ -0,0 +1,48 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), nullptr)); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/my_application.h b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/my_application.h new file mode 100755 index 00000000..6e9f0c3f --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/linux/my_application.h @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/pubspec.yaml new file mode 100755 index 00000000..0a3b93f5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/pubspec.yaml @@ -0,0 +1,28 @@ +name: url_launcher_example +description: Demonstrates how to use the url_launcher plugin. +publish_to: none + +environment: + sdk: ^3.3.0 + flutter: ">=3.19.0" + +dependencies: + flutter: + sdk: flutter + url_launcher_linux: + # When depending on this package from a real application you should use: + # url_launcher_linux: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + url_launcher_platform_interface: ^2.2.0 + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/test_driver/integration_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/test_driver/integration_test.dart new file mode 100755 index 00000000..4f10f2a5 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/lib/url_launcher_linux.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/lib/url_launcher_linux.dart new file mode 100755 index 00000000..b5c85043 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/lib/url_launcher_linux.dart @@ -0,0 +1,75 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:url_launcher_platform_interface/link.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + +import 'src/messages.g.dart'; + +/// An implementation of [UrlLauncherPlatform] for Linux. +class UrlLauncherLinux extends UrlLauncherPlatform { + /// Creates a new URL launcher instance. + UrlLauncherLinux({@visibleForTesting UrlLauncherApi? api}) + : _hostApi = api ?? UrlLauncherApi(); + + /// Registers this class as the default instance of [UrlLauncherPlatform]. + static void registerWith() { + UrlLauncherPlatform.instance = UrlLauncherLinux(); + } + + final UrlLauncherApi _hostApi; + + @override + final LinkDelegate? linkDelegate = null; + + @override + Future canLaunch(String url) async { + return _hostApi.canLaunchUrl(url); + } + + @override + Future launch( + String url, { + required bool useSafariVC, + required bool useWebView, + required bool enableJavaScript, + required bool enableDomStorage, + required bool universalLinksOnly, + required Map headers, + String? webOnlyWindowName, + }) { + // None of the options are supported, so they don't need to be converted to + // LaunchOptions. + return launchUrl(url, const LaunchOptions()); + } + + @override + Future launchUrl(String url, LaunchOptions options) async { + final String? error = await _hostApi.launchUrl(url); + if (error != null) { + // TODO(stuartmorgan): Standardize errors across the entire plugin, + // instead of using PlatformException. This preserves the pre-Pigeon + // behavior of the C code returning this error response. + throw PlatformException( + code: 'Launch Error', message: 'Failed to launch URL: $error'); + } + return true; + } + + @override + Future supportsMode(PreferredLaunchMode mode) async { + return mode == PreferredLaunchMode.platformDefault || + mode == PreferredLaunchMode.externalApplication; + } + + @override + Future supportsCloseForMode(PreferredLaunchMode mode) async { + // No supported mode is closeable. + return false; + } +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/CMakeLists.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/CMakeLists.txt new file mode 100755 index 00000000..a52bd5ad --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/CMakeLists.txt @@ -0,0 +1,65 @@ +cmake_minimum_required(VERSION 3.10) +set(PROJECT_NAME "url_launcher_linux") +project(${PROJECT_NAME} LANGUAGES CXX) + +cmake_policy(VERSION 3.10...3.24) + +set(PLUGIN_NAME "${PROJECT_NAME}_plugin") + +list(APPEND PLUGIN_SOURCES + "messages.g.cc" + "url_launcher_plugin.cc" +) + +add_library(${PLUGIN_NAME} SHARED + ${PLUGIN_SOURCES} +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) +target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) + + +# === Tests === + +if (${include_${PROJECT_NAME}_tests}) +if(${CMAKE_VERSION} VERSION_LESS "3.11.0") +message("Unit tests require CMake 3.11.0 or later") +else() +set(TEST_RUNNER "${PROJECT_NAME}_test") +enable_testing() +# TODO(stuartmorgan): Consider using a single shared, pre-checked-in googletest +# instance rather than downloading for each plugin. This approach makes sense +# for a template, but not for a monorepo with many plugins. +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/release-1.11.0.zip +) +# Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Disable install commands for gtest so it doesn't end up in the bundle. +set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE) + +FetchContent_MakeAvailable(googletest) + +# The plugin's exported API is not very useful for unit testing, so build the +# sources directly into the test binary rather than using the shared library. +add_executable(${TEST_RUNNER} + test/url_launcher_linux_test.cc + ${PLUGIN_SOURCES} +) +apply_standard_settings(${TEST_RUNNER}) +target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") +target_link_libraries(${TEST_RUNNER} PRIVATE flutter) +target_link_libraries(${TEST_RUNNER} PRIVATE PkgConfig::GTK) +target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) + +include(GoogleTest) +gtest_discover_tests(${TEST_RUNNER}) +endif() # CMake version check +endif() # include_${PROJECT_NAME}_tests diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/include/url_launcher_linux/url_launcher_plugin.h b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/include/url_launcher_linux/url_launcher_plugin.h new file mode 100755 index 00000000..f4d19395 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/include/url_launcher_linux/url_launcher_plugin.h @@ -0,0 +1,31 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PACKAGES_URL_LAUNCHER_URL_LAUNCHER_LINUX_LINUX_INCLUDE_URL_LAUNCHER_URL_LAUNCHER_PLUGIN_H_ +#define PACKAGES_URL_LAUNCHER_URL_LAUNCHER_LINUX_LINUX_INCLUDE_URL_LAUNCHER_URL_LAUNCHER_PLUGIN_H_ + +// A plugin to launch URLs. + +#include + +G_BEGIN_DECLS + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define FLUTTER_PLUGIN_EXPORT +#endif + +G_DECLARE_FINAL_TYPE(FlUrlLauncherPlugin, fl_url_launcher_plugin, FL, + URL_LAUNCHER_PLUGIN, GObject) + +FLUTTER_PLUGIN_EXPORT FlUrlLauncherPlugin* fl_url_launcher_plugin_new( + FlPluginRegistrar* registrar); + +FLUTTER_PLUGIN_EXPORT void url_launcher_plugin_register_with_registrar( + FlPluginRegistrar* registrar); + +G_END_DECLS + +#endif // PACKAGES_URL_LAUNCHER_URL_LAUNCHER_LINUX_LINUX_INCLUDE_URL_LAUNCHER_URL_LAUNCHER_PLUGIN_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/messages.g.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/messages.g.cc new file mode 100755 index 00000000..883a5a92 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/messages.g.cc @@ -0,0 +1,300 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v22.6.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#include "messages.g.h" + +struct _FulMessageCodec { + FlStandardMessageCodec parent_instance; +}; + +G_DEFINE_TYPE(FulMessageCodec, ful_message_codec, + fl_standard_message_codec_get_type()) + +static gboolean ful_message_codec_write_value(FlStandardMessageCodec* codec, + GByteArray* buffer, + FlValue* value, GError** error) { + if (fl_value_get_type(value) == FL_VALUE_TYPE_CUSTOM) { + switch (fl_value_get_custom_type(value)) {} + } + + return FL_STANDARD_MESSAGE_CODEC_CLASS(ful_message_codec_parent_class) + ->write_value(codec, buffer, value, error); +} + +static FlValue* ful_message_codec_read_value_of_type( + FlStandardMessageCodec* codec, GBytes* buffer, size_t* offset, int type, + GError** error) { + switch (type) { + default: + return FL_STANDARD_MESSAGE_CODEC_CLASS(ful_message_codec_parent_class) + ->read_value_of_type(codec, buffer, offset, type, error); + } +} + +static void ful_message_codec_init(FulMessageCodec* self) {} + +static void ful_message_codec_class_init(FulMessageCodecClass* klass) { + FL_STANDARD_MESSAGE_CODEC_CLASS(klass)->write_value = + ful_message_codec_write_value; + FL_STANDARD_MESSAGE_CODEC_CLASS(klass)->read_value_of_type = + ful_message_codec_read_value_of_type; +} + +static FulMessageCodec* ful_message_codec_new() { + FulMessageCodec* self = + FUL_MESSAGE_CODEC(g_object_new(ful_message_codec_get_type(), nullptr)); + return self; +} + +struct _FulUrlLauncherApiCanLaunchUrlResponse { + GObject parent_instance; + + FlValue* value; +}; + +G_DEFINE_TYPE(FulUrlLauncherApiCanLaunchUrlResponse, + ful_url_launcher_api_can_launch_url_response, G_TYPE_OBJECT) + +static void ful_url_launcher_api_can_launch_url_response_dispose( + GObject* object) { + FulUrlLauncherApiCanLaunchUrlResponse* self = + FUL_URL_LAUNCHER_API_CAN_LAUNCH_URL_RESPONSE(object); + g_clear_pointer(&self->value, fl_value_unref); + G_OBJECT_CLASS(ful_url_launcher_api_can_launch_url_response_parent_class) + ->dispose(object); +} + +static void ful_url_launcher_api_can_launch_url_response_init( + FulUrlLauncherApiCanLaunchUrlResponse* self) {} + +static void ful_url_launcher_api_can_launch_url_response_class_init( + FulUrlLauncherApiCanLaunchUrlResponseClass* klass) { + G_OBJECT_CLASS(klass)->dispose = + ful_url_launcher_api_can_launch_url_response_dispose; +} + +FulUrlLauncherApiCanLaunchUrlResponse* +ful_url_launcher_api_can_launch_url_response_new(gboolean return_value) { + FulUrlLauncherApiCanLaunchUrlResponse* self = + FUL_URL_LAUNCHER_API_CAN_LAUNCH_URL_RESPONSE(g_object_new( + ful_url_launcher_api_can_launch_url_response_get_type(), nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_bool(return_value)); + return self; +} + +FulUrlLauncherApiCanLaunchUrlResponse* +ful_url_launcher_api_can_launch_url_response_new_error(const gchar* code, + const gchar* message, + FlValue* details) { + FulUrlLauncherApiCanLaunchUrlResponse* self = + FUL_URL_LAUNCHER_API_CAN_LAUNCH_URL_RESPONSE(g_object_new( + ful_url_launcher_api_can_launch_url_response_get_type(), nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_string(code)); + fl_value_append_take(self->value, + fl_value_new_string(message != nullptr ? message : "")); + fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details) + : fl_value_new_null()); + return self; +} + +struct _FulUrlLauncherApiLaunchUrlResponse { + GObject parent_instance; + + FlValue* value; +}; + +G_DEFINE_TYPE(FulUrlLauncherApiLaunchUrlResponse, + ful_url_launcher_api_launch_url_response, G_TYPE_OBJECT) + +static void ful_url_launcher_api_launch_url_response_dispose(GObject* object) { + FulUrlLauncherApiLaunchUrlResponse* self = + FUL_URL_LAUNCHER_API_LAUNCH_URL_RESPONSE(object); + g_clear_pointer(&self->value, fl_value_unref); + G_OBJECT_CLASS(ful_url_launcher_api_launch_url_response_parent_class) + ->dispose(object); +} + +static void ful_url_launcher_api_launch_url_response_init( + FulUrlLauncherApiLaunchUrlResponse* self) {} + +static void ful_url_launcher_api_launch_url_response_class_init( + FulUrlLauncherApiLaunchUrlResponseClass* klass) { + G_OBJECT_CLASS(klass)->dispose = + ful_url_launcher_api_launch_url_response_dispose; +} + +FulUrlLauncherApiLaunchUrlResponse* +ful_url_launcher_api_launch_url_response_new(const gchar* return_value) { + FulUrlLauncherApiLaunchUrlResponse* self = + FUL_URL_LAUNCHER_API_LAUNCH_URL_RESPONSE(g_object_new( + ful_url_launcher_api_launch_url_response_get_type(), nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, return_value != nullptr + ? fl_value_new_string(return_value) + : fl_value_new_null()); + return self; +} + +FulUrlLauncherApiLaunchUrlResponse* +ful_url_launcher_api_launch_url_response_new_error(const gchar* code, + const gchar* message, + FlValue* details) { + FulUrlLauncherApiLaunchUrlResponse* self = + FUL_URL_LAUNCHER_API_LAUNCH_URL_RESPONSE(g_object_new( + ful_url_launcher_api_launch_url_response_get_type(), nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_string(code)); + fl_value_append_take(self->value, + fl_value_new_string(message != nullptr ? message : "")); + fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details) + : fl_value_new_null()); + return self; +} + +struct _FulUrlLauncherApi { + GObject parent_instance; + + const FulUrlLauncherApiVTable* vtable; + gpointer user_data; + GDestroyNotify user_data_free_func; +}; + +G_DEFINE_TYPE(FulUrlLauncherApi, ful_url_launcher_api, G_TYPE_OBJECT) + +static void ful_url_launcher_api_dispose(GObject* object) { + FulUrlLauncherApi* self = FUL_URL_LAUNCHER_API(object); + if (self->user_data != nullptr) { + self->user_data_free_func(self->user_data); + } + self->user_data = nullptr; + G_OBJECT_CLASS(ful_url_launcher_api_parent_class)->dispose(object); +} + +static void ful_url_launcher_api_init(FulUrlLauncherApi* self) {} + +static void ful_url_launcher_api_class_init(FulUrlLauncherApiClass* klass) { + G_OBJECT_CLASS(klass)->dispose = ful_url_launcher_api_dispose; +} + +static FulUrlLauncherApi* ful_url_launcher_api_new( + const FulUrlLauncherApiVTable* vtable, gpointer user_data, + GDestroyNotify user_data_free_func) { + FulUrlLauncherApi* self = FUL_URL_LAUNCHER_API( + g_object_new(ful_url_launcher_api_get_type(), nullptr)); + self->vtable = vtable; + self->user_data = user_data; + self->user_data_free_func = user_data_free_func; + return self; +} + +static void ful_url_launcher_api_can_launch_url_cb( + FlBasicMessageChannel* channel, FlValue* message_, + FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { + FulUrlLauncherApi* self = FUL_URL_LAUNCHER_API(user_data); + + if (self->vtable == nullptr || self->vtable->can_launch_url == nullptr) { + return; + } + + FlValue* value0 = fl_value_get_list_value(message_, 0); + const gchar* url = fl_value_get_string(value0); + g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response = + self->vtable->can_launch_url(url, self->user_data); + if (response == nullptr) { + g_warning("No response returned to %s.%s", "UrlLauncherApi", + "canLaunchUrl"); + return; + } + + g_autoptr(GError) error = NULL; + if (!fl_basic_message_channel_respond(channel, response_handle, + response->value, &error)) { + g_warning("Failed to send response to %s.%s: %s", "UrlLauncherApi", + "canLaunchUrl", error->message); + } +} + +static void ful_url_launcher_api_launch_url_cb( + FlBasicMessageChannel* channel, FlValue* message_, + FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { + FulUrlLauncherApi* self = FUL_URL_LAUNCHER_API(user_data); + + if (self->vtable == nullptr || self->vtable->launch_url == nullptr) { + return; + } + + FlValue* value0 = fl_value_get_list_value(message_, 0); + const gchar* url = fl_value_get_string(value0); + g_autoptr(FulUrlLauncherApiLaunchUrlResponse) response = + self->vtable->launch_url(url, self->user_data); + if (response == nullptr) { + g_warning("No response returned to %s.%s", "UrlLauncherApi", "launchUrl"); + return; + } + + g_autoptr(GError) error = NULL; + if (!fl_basic_message_channel_respond(channel, response_handle, + response->value, &error)) { + g_warning("Failed to send response to %s.%s: %s", "UrlLauncherApi", + "launchUrl", error->message); + } +} + +void ful_url_launcher_api_set_method_handlers( + FlBinaryMessenger* messenger, const gchar* suffix, + const FulUrlLauncherApiVTable* vtable, gpointer user_data, + GDestroyNotify user_data_free_func) { + g_autofree gchar* dot_suffix = + suffix != nullptr ? g_strdup_printf(".%s", suffix) : g_strdup(""); + g_autoptr(FulUrlLauncherApi) api_data = + ful_url_launcher_api_new(vtable, user_data, user_data_free_func); + + g_autoptr(FulMessageCodec) codec = ful_message_codec_new(); + g_autofree gchar* can_launch_url_channel_name = g_strdup_printf( + "dev.flutter.pigeon.url_launcher_linux.UrlLauncherApi.canLaunchUrl%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) can_launch_url_channel = + fl_basic_message_channel_new(messenger, can_launch_url_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler( + can_launch_url_channel, ful_url_launcher_api_can_launch_url_cb, + g_object_ref(api_data), g_object_unref); + g_autofree gchar* launch_url_channel_name = g_strdup_printf( + "dev.flutter.pigeon.url_launcher_linux.UrlLauncherApi.launchUrl%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) launch_url_channel = + fl_basic_message_channel_new(messenger, launch_url_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler( + launch_url_channel, ful_url_launcher_api_launch_url_cb, + g_object_ref(api_data), g_object_unref); +} + +void ful_url_launcher_api_clear_method_handlers(FlBinaryMessenger* messenger, + const gchar* suffix) { + g_autofree gchar* dot_suffix = + suffix != nullptr ? g_strdup_printf(".%s", suffix) : g_strdup(""); + + g_autoptr(FulMessageCodec) codec = ful_message_codec_new(); + g_autofree gchar* can_launch_url_channel_name = g_strdup_printf( + "dev.flutter.pigeon.url_launcher_linux.UrlLauncherApi.canLaunchUrl%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) can_launch_url_channel = + fl_basic_message_channel_new(messenger, can_launch_url_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler(can_launch_url_channel, nullptr, + nullptr, nullptr); + g_autofree gchar* launch_url_channel_name = g_strdup_printf( + "dev.flutter.pigeon.url_launcher_linux.UrlLauncherApi.launchUrl%s", + dot_suffix); + g_autoptr(FlBasicMessageChannel) launch_url_channel = + fl_basic_message_channel_new(messenger, launch_url_channel_name, + FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler(launch_url_channel, nullptr, + nullptr, nullptr); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/messages.g.h b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/messages.g.h new file mode 100755 index 00000000..1b23f248 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/messages.g.h @@ -0,0 +1,121 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v22.6.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#ifndef PIGEON_MESSAGES_G_H_ +#define PIGEON_MESSAGES_G_H_ + +#include + +G_BEGIN_DECLS + +G_DECLARE_FINAL_TYPE(FulMessageCodec, ful_message_codec, FUL, MESSAGE_CODEC, + FlStandardMessageCodec) + +G_DECLARE_FINAL_TYPE(FulUrlLauncherApi, ful_url_launcher_api, FUL, + URL_LAUNCHER_API, GObject) + +G_DECLARE_FINAL_TYPE(FulUrlLauncherApiCanLaunchUrlResponse, + ful_url_launcher_api_can_launch_url_response, FUL, + URL_LAUNCHER_API_CAN_LAUNCH_URL_RESPONSE, GObject) + +/** + * ful_url_launcher_api_can_launch_url_response_new: + * + * Creates a new response to UrlLauncherApi.canLaunchUrl. + * + * Returns: a new #FulUrlLauncherApiCanLaunchUrlResponse + */ +FulUrlLauncherApiCanLaunchUrlResponse* +ful_url_launcher_api_can_launch_url_response_new(gboolean return_value); + +/** + * ful_url_launcher_api_can_launch_url_response_new_error: + * @code: error code. + * @message: error message. + * @details: (allow-none): error details or %NULL. + * + * Creates a new error response to UrlLauncherApi.canLaunchUrl. + * + * Returns: a new #FulUrlLauncherApiCanLaunchUrlResponse + */ +FulUrlLauncherApiCanLaunchUrlResponse* +ful_url_launcher_api_can_launch_url_response_new_error(const gchar* code, + const gchar* message, + FlValue* details); + +G_DECLARE_FINAL_TYPE(FulUrlLauncherApiLaunchUrlResponse, + ful_url_launcher_api_launch_url_response, FUL, + URL_LAUNCHER_API_LAUNCH_URL_RESPONSE, GObject) + +/** + * ful_url_launcher_api_launch_url_response_new: + * + * Creates a new response to UrlLauncherApi.launchUrl. + * + * Returns: a new #FulUrlLauncherApiLaunchUrlResponse + */ +FulUrlLauncherApiLaunchUrlResponse* +ful_url_launcher_api_launch_url_response_new(const gchar* return_value); + +/** + * ful_url_launcher_api_launch_url_response_new_error: + * @code: error code. + * @message: error message. + * @details: (allow-none): error details or %NULL. + * + * Creates a new error response to UrlLauncherApi.launchUrl. + * + * Returns: a new #FulUrlLauncherApiLaunchUrlResponse + */ +FulUrlLauncherApiLaunchUrlResponse* +ful_url_launcher_api_launch_url_response_new_error(const gchar* code, + const gchar* message, + FlValue* details); + +/** + * FulUrlLauncherApiVTable: + * + * Table of functions exposed by UrlLauncherApi to be implemented by the API + * provider. + */ +typedef struct { + FulUrlLauncherApiCanLaunchUrlResponse* (*can_launch_url)(const gchar* url, + gpointer user_data); + FulUrlLauncherApiLaunchUrlResponse* (*launch_url)(const gchar* url, + gpointer user_data); +} FulUrlLauncherApiVTable; + +/** + * ful_url_launcher_api_set_method_handlers: + * + * @messenger: an #FlBinaryMessenger. + * @suffix: (allow-none): a suffix to add to the API or %NULL for none. + * @vtable: implementations of the methods in this API. + * @user_data: (closure): user data to pass to the functions in @vtable. + * @user_data_free_func: (allow-none): a function which gets called to free + * @user_data, or %NULL. + * + * Connects the method handlers in the UrlLauncherApi API. + */ +void ful_url_launcher_api_set_method_handlers( + FlBinaryMessenger* messenger, const gchar* suffix, + const FulUrlLauncherApiVTable* vtable, gpointer user_data, + GDestroyNotify user_data_free_func); + +/** + * ful_url_launcher_api_clear_method_handlers: + * + * @messenger: an #FlBinaryMessenger. + * @suffix: (allow-none): a suffix to add to the API or %NULL for none. + * + * Clears the method handlers in the UrlLauncherApi API. + */ +void ful_url_launcher_api_clear_method_handlers(FlBinaryMessenger* messenger, + const gchar* suffix); + +G_END_DECLS + +#endif // PIGEON_MESSAGES_G_H_ diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/test/url_launcher_linux_test.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/test/url_launcher_linux_test.cc new file mode 100755 index 00000000..f5a5fdbf --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/test/url_launcher_linux_test.cc @@ -0,0 +1,85 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include +#include +#include + +#include +#include + +#include "include/url_launcher_linux/url_launcher_plugin.h" +#include "url_launcher_plugin_private.h" + +// Re-declare the opaque struct as a temporary workaround for the lack of +// APIs for reading host API response objects. +// TODO(stuartmorgan): Remove this once the following is fixed: +// https://github.com/flutter/flutter/issues/152166. +struct _FulUrlLauncherApiCanLaunchUrlResponse { + GObject parent_instance; + + FlValue* value; +}; + +namespace url_launcher_plugin { +namespace test { + +TEST(UrlLauncherPlugin, CanLaunchSuccess) { + g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response = + handle_can_launch_url("https://flutter.dev", nullptr); + ASSERT_NE(response, nullptr); + ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST); + ASSERT_TRUE(fl_value_get_length(response->value) == 1); + g_autoptr(FlValue) expected = fl_value_new_bool(true); + EXPECT_TRUE( + fl_value_equal(fl_value_get_list_value(response->value, 0), expected)); +} + +TEST(UrlLauncherPlugin, CanLaunchFailureUnhandled) { + g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response = + handle_can_launch_url("madeup:scheme", nullptr); + ASSERT_NE(response, nullptr); + ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST); + ASSERT_TRUE(fl_value_get_length(response->value) == 1); + g_autoptr(FlValue) expected = fl_value_new_bool(false); + EXPECT_TRUE( + fl_value_equal(fl_value_get_list_value(response->value, 0), expected)); +} + +TEST(UrlLauncherPlugin, CanLaunchFileSuccess) { + g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response = + handle_can_launch_url("file:///", nullptr); + ASSERT_NE(response, nullptr); + ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST); + ASSERT_TRUE(fl_value_get_length(response->value) == 1); + g_autoptr(FlValue) expected = fl_value_new_bool(true); + EXPECT_TRUE( + fl_value_equal(fl_value_get_list_value(response->value, 0), expected)); +} + +TEST(UrlLauncherPlugin, CanLaunchFailureInvalidFileExtension) { + g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response = + handle_can_launch_url("file:///madeup.madeupextension", nullptr); + ASSERT_NE(response, nullptr); + ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST); + ASSERT_TRUE(fl_value_get_length(response->value) == 1); + g_autoptr(FlValue) expected = fl_value_new_bool(false); + EXPECT_TRUE( + fl_value_equal(fl_value_get_list_value(response->value, 0), expected)); +} + +// For consistency with the established mobile implementations, +// an invalid URL should return false, not an error. +TEST(UrlLauncherPlugin, CanLaunchFailureInvalidUrl) { + g_autoptr(FulUrlLauncherApiCanLaunchUrlResponse) response = + handle_can_launch_url("", nullptr); + ASSERT_NE(response, nullptr); + ASSERT_TRUE(fl_value_get_type(response->value) == FL_VALUE_TYPE_LIST); + ASSERT_TRUE(fl_value_get_length(response->value) == 1); + g_autoptr(FlValue) expected = fl_value_new_bool(false); + EXPECT_TRUE( + fl_value_equal(fl_value_get_list_value(response->value, 0), expected)); +} + +} // namespace test +} // namespace url_launcher_plugin diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/url_launcher_plugin.cc b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/url_launcher_plugin.cc new file mode 100755 index 00000000..0b814f8b --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/url_launcher_plugin.cc @@ -0,0 +1,109 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "include/url_launcher_linux/url_launcher_plugin.h" + +#include +#include + +#include + +#include "messages.g.h" +#include "url_launcher_plugin_private.h" + +struct _FlUrlLauncherPlugin { + GObject parent_instance; + + FlPluginRegistrar* registrar; +}; + +G_DEFINE_TYPE(FlUrlLauncherPlugin, fl_url_launcher_plugin, g_object_get_type()) + +// Checks if URI has launchable file resource. +static gboolean can_launch_uri_with_file_resource(FlUrlLauncherPlugin* self, + const gchar* url) { + g_autoptr(GError) error = nullptr; + g_autoptr(GFile) file = g_file_new_for_uri(url); + g_autoptr(GAppInfo) app_info = + g_file_query_default_handler(file, NULL, &error); + return app_info != nullptr; +} + +FulUrlLauncherApiCanLaunchUrlResponse* handle_can_launch_url( + const gchar* url, gpointer user_data) { + FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN(user_data); + + gboolean is_launchable = FALSE; + g_autofree gchar* scheme = g_uri_parse_scheme(url); + if (scheme != nullptr) { + g_autoptr(GAppInfo) app_info = + g_app_info_get_default_for_uri_scheme(scheme); + is_launchable = app_info != nullptr; + + if (!is_launchable) { + is_launchable = can_launch_uri_with_file_resource(self, url); + } + } + + return ful_url_launcher_api_can_launch_url_response_new(is_launchable); +} + +// Called when a URL should launch. +static FulUrlLauncherApiLaunchUrlResponse* handle_launch_url( + const gchar* url, gpointer user_data) { + FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN(user_data); + + FlView* view = fl_plugin_registrar_get_view(self->registrar); + g_autoptr(GError) error = nullptr; + gboolean launched; + if (view != nullptr) { + GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))); + launched = gtk_show_uri_on_window(window, url, GDK_CURRENT_TIME, &error); + } else { + launched = g_app_info_launch_default_for_uri(url, nullptr, &error); + } + if (!launched) { + return ful_url_launcher_api_launch_url_response_new(error->message); + } + + return ful_url_launcher_api_launch_url_response_new(nullptr); +} + +static void fl_url_launcher_plugin_dispose(GObject* object) { + FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN(object); + + ful_url_launcher_api_clear_method_handlers( + fl_plugin_registrar_get_messenger(self->registrar), nullptr); + g_clear_object(&self->registrar); + + G_OBJECT_CLASS(fl_url_launcher_plugin_parent_class)->dispose(object); +} + +static void fl_url_launcher_plugin_class_init(FlUrlLauncherPluginClass* klass) { + G_OBJECT_CLASS(klass)->dispose = fl_url_launcher_plugin_dispose; +} + +FlUrlLauncherPlugin* fl_url_launcher_plugin_new(FlPluginRegistrar* registrar) { + FlUrlLauncherPlugin* self = FL_URL_LAUNCHER_PLUGIN( + g_object_new(fl_url_launcher_plugin_get_type(), nullptr)); + + self->registrar = FL_PLUGIN_REGISTRAR(g_object_ref(registrar)); + + static FulUrlLauncherApiVTable api_vtable = { + .can_launch_url = handle_can_launch_url, + .launch_url = handle_launch_url, + }; + ful_url_launcher_api_set_method_handlers( + fl_plugin_registrar_get_messenger(registrar), nullptr, &api_vtable, + g_object_ref(self), g_object_unref); + + return self; +} + +static void fl_url_launcher_plugin_init(FlUrlLauncherPlugin* self) {} + +void url_launcher_plugin_register_with_registrar(FlPluginRegistrar* registrar) { + FlUrlLauncherPlugin* plugin = fl_url_launcher_plugin_new(registrar); + g_object_unref(plugin); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/url_launcher_plugin_private.h b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/url_launcher_plugin_private.h new file mode 100755 index 00000000..9284ea80 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/linux/url_launcher_plugin_private.h @@ -0,0 +1,12 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include "include/url_launcher_linux/url_launcher_plugin.h" +#include "messages.g.h" + +// Called to check if a URL can be launched. +FulUrlLauncherApiCanLaunchUrlResponse* handle_can_launch_url( + const gchar* url, gpointer user_data); diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pigeons/copyright.txt b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pigeons/copyright.txt new file mode 100755 index 00000000..1236b63c --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pigeons/messages.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pigeons/messages.dart new file mode 100755 index 00000000..56d30d75 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pigeons/messages.dart @@ -0,0 +1,21 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon(PigeonOptions( + dartOut: 'lib/src/messages.g.dart', + gobjectHeaderOut: 'linux/messages.g.h', + gobjectSourceOut: 'linux/messages.g.cc', + gobjectOptions: GObjectOptions(module: 'Ful'), + copyrightHeader: 'pigeons/copyright.txt', +)) +@HostApi() +abstract class UrlLauncherApi { + /// Returns true if the URL can definitely be launched. + bool canLaunchUrl(String url); + + /// Opens the URL externally, returning an error string on failure. + String? launchUrl(String url); +} diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pubspec.yaml b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pubspec.yaml new file mode 100755 index 00000000..fa1b4519 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/pubspec.yaml @@ -0,0 +1,34 @@ +name: url_launcher_linux +description: Linux implementation of the url_launcher plugin. +repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_linux +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22 +version: 3.2.1 + +environment: + sdk: ^3.3.0 + flutter: ">=3.19.0" + +flutter: + plugin: + implements: url_launcher + platforms: + linux: + pluginClass: UrlLauncherPlugin + dartPluginClass: UrlLauncherLinux + +dependencies: + flutter: + sdk: flutter + url_launcher_platform_interface: ^2.2.0 + +dev_dependencies: + flutter_test: + sdk: flutter + pigeon: ^22.6.1 + test: ^1.16.3 + +topics: + - links + - os-integration + - url-launcher + - urls diff --git a/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/test/url_launcher_linux_test.dart b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/test/url_launcher_linux_test.dart new file mode 100755 index 00000000..7b9bba40 --- /dev/null +++ b/app/linux/flutter/ephemeral/.plugin_symlinks/url_launcher_linux/test/url_launcher_linux_test.dart @@ -0,0 +1,175 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:url_launcher_linux/src/messages.g.dart'; +import 'package:url_launcher_linux/url_launcher_linux.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + +void main() { + group('UrlLauncherLinux', () { + test('registers instance', () { + UrlLauncherLinux.registerWith(); + expect(UrlLauncherPlatform.instance, isA()); + }); + + test('canLaunch passes true', () async { + final _FakeUrlLauncherApi api = _FakeUrlLauncherApi(); + final UrlLauncherLinux launcher = UrlLauncherLinux(api: api); + + final bool canLaunch = await launcher.canLaunch('http://example.com/'); + + expect(canLaunch, true); + }); + + test('canLaunch passes false', () async { + final _FakeUrlLauncherApi api = _FakeUrlLauncherApi(canLaunch: false); + final UrlLauncherLinux launcher = UrlLauncherLinux(api: api); + + final bool canLaunch = await launcher.canLaunch('http://example.com/'); + + expect(canLaunch, false); + }); + + test('launch', () async { + final _FakeUrlLauncherApi api = _FakeUrlLauncherApi(); + final UrlLauncherLinux launcher = UrlLauncherLinux(api: api); + const String url = 'http://example.com/'; + + final bool launched = await launcher.launch( + url, + useSafariVC: true, + useWebView: false, + enableJavaScript: false, + enableDomStorage: false, + universalLinksOnly: false, + headers: const {}, + ); + + expect(launched, true); + expect(api.argument, url); + }); + + test('launch should throw if platform returns an error', () async { + final _FakeUrlLauncherApi api = _FakeUrlLauncherApi(error: 'An error'); + final UrlLauncherLinux launcher = UrlLauncherLinux(api: api); + + await expectLater( + launcher.launch( + 'http://example.com/', + useSafariVC: true, + useWebView: false, + enableJavaScript: false, + enableDomStorage: false, + universalLinksOnly: false, + headers: const {}, + ), + throwsA(isA() + .having((PlatformException e) => e.code, 'code', 'Launch Error') + .having((PlatformException e) => e.message, 'message', + contains('Failed to launch URL: An error')))); + }); + + group('launchUrl', () { + test('passes URL', () async { + final _FakeUrlLauncherApi api = _FakeUrlLauncherApi(); + final UrlLauncherLinux launcher = UrlLauncherLinux(api: api); + const String url = 'http://example.com/'; + + final bool launched = + await launcher.launchUrl(url, const LaunchOptions()); + + expect(launched, true); + expect(api.argument, url); + }); + + test('throws if platform returns an error', () async { + final _FakeUrlLauncherApi api = _FakeUrlLauncherApi(error: 'An error'); + final UrlLauncherLinux launcher = UrlLauncherLinux(api: api); + + await expectLater( + launcher.launchUrl('http://example.com/', const LaunchOptions()), + throwsA(isA() + .having((PlatformException e) => e.code, 'code', 'Launch Error') + .having((PlatformException e) => e.message, 'message', + contains('Failed to launch URL: An error')))); + }); + }); + + group('supportsMode', () { + test('returns true for platformDefault', () async { + final UrlLauncherLinux launcher = UrlLauncherLinux(); + expect(await launcher.supportsMode(PreferredLaunchMode.platformDefault), + true); + }); + + test('returns true for external application', () async { + final UrlLauncherLinux launcher = UrlLauncherLinux(); + expect( + await launcher + .supportsMode(PreferredLaunchMode.externalApplication), + true); + }); + + test('returns false for other modes', () async { + final UrlLauncherLinux launcher = UrlLauncherLinux(); + expect( + await launcher.supportsMode( + PreferredLaunchMode.externalNonBrowserApplication), + false); + expect( + await launcher.supportsMode(PreferredLaunchMode.inAppBrowserView), + false); + expect(await launcher.supportsMode(PreferredLaunchMode.inAppWebView), + false); + }); + }); + + test('supportsCloseForMode returns false', () async { + final UrlLauncherLinux launcher = UrlLauncherLinux(); + expect( + await launcher + .supportsCloseForMode(PreferredLaunchMode.platformDefault), + false); + expect( + await launcher + .supportsCloseForMode(PreferredLaunchMode.externalApplication), + false); + }); + }); +} + +class _FakeUrlLauncherApi implements UrlLauncherApi { + _FakeUrlLauncherApi({this.canLaunch = true, this.error}); + + /// The value to return from canLaunch. + final bool canLaunch; + + /// The error to return from launchUrl, if any. + final String? error; + + /// The argument that was passed to an API call. + String? argument; + + @override + Future canLaunchUrl(String url) async { + argument = url; + return canLaunch; + } + + @override + Future launchUrl(String url) async { + argument = url; + return error; + } + + @override + // ignore: non_constant_identifier_names + BinaryMessenger? get pigeonVar_binaryMessenger => null; + + @override + // ignore: non_constant_identifier_names + String get pigeonVar_messageChannelSuffix => ''; +} diff --git a/app/linux/flutter/generated_plugin_registrant.cc b/app/linux/flutter/generated_plugin_registrant.cc old mode 100644 new mode 100755 diff --git a/app/linux/flutter/generated_plugin_registrant.h b/app/linux/flutter/generated_plugin_registrant.h old mode 100644 new mode 100755 diff --git a/app/linux/flutter/generated_plugins.cmake b/app/linux/flutter/generated_plugins.cmake old mode 100644 new mode 100755 diff --git a/app/linux/runner/CMakeLists.txt b/app/linux/runner/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/app/linux/runner/main.cc b/app/linux/runner/main.cc old mode 100644 new mode 100755 diff --git a/app/linux/runner/my_application.cc b/app/linux/runner/my_application.cc old mode 100644 new mode 100755 diff --git a/app/linux/runner/my_application.h b/app/linux/runner/my_application.h old mode 100644 new mode 100755 diff --git a/app/macos/Flutter/Flutter-Debug.xcconfig b/app/macos/Flutter/Flutter-Debug.xcconfig old mode 100644 new mode 100755 diff --git a/app/macos/Flutter/Flutter-Release.xcconfig b/app/macos/Flutter/Flutter-Release.xcconfig old mode 100644 new mode 100755 diff --git a/app/macos/Flutter/GeneratedPluginRegistrant.swift b/app/macos/Flutter/GeneratedPluginRegistrant.swift old mode 100644 new mode 100755 diff --git a/app/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/app/macos/Flutter/ephemeral/Flutter-Generated.xcconfig old mode 100644 new mode 100755 index 3984b9fa..5812b667 --- a/app/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/app/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -1,10 +1,10 @@ // This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=/home/pierre/.local/flutter +FLUTTER_ROOT=/opt/flutter FLUTTER_APPLICATION_PATH=/home/pierre/dev/geosector/app COCOAPODS_PARALLEL_CODE_SIGN=true FLUTTER_BUILD_DIR=build -FLUTTER_BUILD_NAME=3.6.3 -FLUTTER_BUILD_NUMBER=363 +FLUTTER_BUILD_NAME=26.01.2605 +FLUTTER_BUILD_NUMBER=26012605 DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true TREE_SHAKE_ICONS=false diff --git a/app/macos/Flutter/ephemeral/flutter_export_environment.sh b/app/macos/Flutter/ephemeral/flutter_export_environment.sh index 60f170df..be1c85ed 100755 --- a/app/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/app/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -1,11 +1,11 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=/home/pierre/.local/flutter" +export "FLUTTER_ROOT=/opt/flutter" export "FLUTTER_APPLICATION_PATH=/home/pierre/dev/geosector/app" export "COCOAPODS_PARALLEL_CODE_SIGN=true" export "FLUTTER_BUILD_DIR=build" -export "FLUTTER_BUILD_NAME=3.6.3" -export "FLUTTER_BUILD_NUMBER=363" +export "FLUTTER_BUILD_NAME=26.01.2605" +export "FLUTTER_BUILD_NUMBER=26012605" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" diff --git a/app/macos/Podfile b/app/macos/Podfile old mode 100644 new mode 100755 diff --git a/app/macos/Runner.xcodeproj/project.pbxproj b/app/macos/Runner.xcodeproj/project.pbxproj old mode 100644 new mode 100755 diff --git a/app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist old mode 100644 new mode 100755 diff --git a/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme old mode 100644 new mode 100755 diff --git a/app/macos/Runner.xcworkspace/contents.xcworkspacedata b/app/macos/Runner.xcworkspace/contents.xcworkspacedata old mode 100644 new mode 100755 diff --git a/app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist old mode 100644 new mode 100755 diff --git a/app/macos/Runner/AppDelegate.swift b/app/macos/Runner/AppDelegate.swift old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/app/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Base.lproj/MainMenu.xib b/app/macos/Runner/Base.lproj/MainMenu.xib old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Configs/AppInfo.xcconfig b/app/macos/Runner/Configs/AppInfo.xcconfig old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Configs/Debug.xcconfig b/app/macos/Runner/Configs/Debug.xcconfig old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Configs/Release.xcconfig b/app/macos/Runner/Configs/Release.xcconfig old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Configs/Warnings.xcconfig b/app/macos/Runner/Configs/Warnings.xcconfig old mode 100644 new mode 100755 diff --git a/app/macos/Runner/DebugProfile.entitlements b/app/macos/Runner/DebugProfile.entitlements old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Info.plist b/app/macos/Runner/Info.plist old mode 100644 new mode 100755 diff --git a/app/macos/Runner/MainFlutterWindow.swift b/app/macos/Runner/MainFlutterWindow.swift old mode 100644 new mode 100755 diff --git a/app/macos/Runner/Release.entitlements b/app/macos/Runner/Release.entitlements old mode 100644 new mode 100755 diff --git a/app/macos/RunnerTests/RunnerTests.swift b/app/macos/RunnerTests/RunnerTests.swift old mode 100644 new mode 100755 diff --git a/app/pubspec-tests-ios.yaml b/app/pubspec-tests-ios.yaml old mode 100644 new mode 100755 diff --git a/app/pubspec.lock b/app/pubspec.lock old mode 100644 new mode 100755 diff --git a/app/pubspec.yaml b/app/pubspec.yaml index f539e159..df2bb5de 100755 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -1,7 +1,7 @@ name: geosector_app description: 'GEOSECTOR - Gestion de distribution des calendriers par secteurs géographiques pour les amicales de pompiers' publish_to: 'none' -version: 3.6.3+363 +version: 26.01.2605+26012605 environment: sdk: '>=3.0.0 <4.0.0' diff --git a/app/pubspec.yaml.bak b/app/pubspec.yaml.bak index f539e159..9d173d9d 100755 --- a/app/pubspec.yaml.bak +++ b/app/pubspec.yaml.bak @@ -1,7 +1,7 @@ name: geosector_app description: 'GEOSECTOR - Gestion de distribution des calendriers par secteurs géographiques pour les amicales de pompiers' publish_to: 'none' -version: 3.6.3+363 +version: 3.6.4+364 environment: sdk: '>=3.0.0 <4.0.0' diff --git a/app/ralph b/app/ralph new file mode 160000 index 00000000..098579b5 --- /dev/null +++ b/app/ralph @@ -0,0 +1 @@ +Subproject commit 098579b5a124fa3c5e91e629fbc93a736bf3ccdf diff --git a/app/store_assets/geosector-1024x500.png b/app/store_assets/geosector-1024x500.png old mode 100644 new mode 100755 diff --git a/app/store_assets/geosector-admin-amicale-1800x1800.png b/app/store_assets/geosector-admin-amicale-1800x1800.png old mode 100644 new mode 100755 diff --git a/app/store_assets/geosector-admin-tbord-1800x1800.png b/app/store_assets/geosector-admin-tbord-1800x1800.png old mode 100644 new mode 100755 diff --git a/app/store_assets/geosector-user-carte-1800x1800.png b/app/store_assets/geosector-user-carte-1800x1800.png old mode 100644 new mode 100755 diff --git a/app/store_assets/geosector-user-histo-1800x1800.png b/app/store_assets/geosector-user-histo-1800x1800.png old mode 100644 new mode 100755 diff --git a/app/store_assets/geosector-user-login-1800x1800.png b/app/store_assets/geosector-user-login-1800x1800.png old mode 100644 new mode 100755 diff --git a/app/store_assets/geosector-user-stripe-1800x1800.png b/app/store_assets/geosector-user-stripe-1800x1800.png old mode 100644 new mode 100755 diff --git a/app/store_assets/geosector-user-tbord-1800x1800.png b/app/store_assets/geosector-user-tbord-1800x1800.png old mode 100644 new mode 100755 diff --git a/app/store_assets/geosector_map_admin.png b/app/store_assets/geosector_map_admin.png old mode 100644 new mode 100755 diff --git a/app/tests-android.md b/app/tests-android.md old mode 100644 new mode 100755 diff --git a/app/tests-iphone.md b/app/tests-iphone.md old mode 100644 new mode 100755 diff --git a/app/windows/CMakeLists.txt b/app/windows/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/app/windows/flutter/CMakeLists.txt b/app/windows/flutter/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus deleted file mode 120000 index 27846f43..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/battery_plus-6.0.3/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/CHANGELOG.md new file mode 100755 index 00000000..cee757d6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/CHANGELOG.md @@ -0,0 +1,372 @@ +## 6.0.3 + + - **CHORE**(battery_plus): Update to package:web to ^1.0.0 ([#3103](https://github.com/fluttercommunity/plus_plugins/pull/3103)). ([cf534eec](https://github.com/fluttercommunity/plus_plugins/commit/cf534eec402b57b70ffe96bf5351afcdfa8c7c7e)) + - **FIX**(battery_plus): Fix type conversion ([#3159](https://github.com/fluttercommunity/plus_plugins/issues/3159)). ([1145af14](https://github.com/fluttercommunity/plus_plugins/commit/1145af14298ecab7d7be57bfa9a32c628b9acdf3)) + - **FIX**(battery_plus): Fix crash when retrieving battery level on desktop Mac. ([#3155](https://github.com/fluttercommunity/plus_plugins/issues/3155)). ([36e7dd16](https://github.com/fluttercommunity/plus_plugins/commit/36e7dd16de3ac43d83eeece7e682b265c93f2fbe)) + - **DOCS**(battery_plus): Update plugin requirements ([#3158](https://github.com/fluttercommunity/plus_plugins/issues/3158)). ([c0353107](https://github.com/fluttercommunity/plus_plugins/commit/c0353107f17e5e32ca33e44742343ccd2c391a0c)) + +## 6.0.2 + + - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) + - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) + +## 6.0.1 + + - **REFACTOR**(battery_plus): Migrate Android example to use the new plugins declaration ([#2772](https://github.com/fluttercommunity/plus_plugins/issues/2772)). ([740a5df2](https://github.com/fluttercommunity/plus_plugins/commit/740a5df21fb84df2b88cea822d53302ce61a6dc2)) + - **FIX**(battery_plus): Fix return value of getBattery to be nullable ([#2745](https://github.com/fluttercommunity/plus_plugins/issues/2745)). ([4d5b950e](https://github.com/fluttercommunity/plus_plugins/commit/4d5b950ed1c74f801f621ef0c07b44f496a7465b)) + +## 6.0.0 + +> Note: This release has breaking changes. + +In this release plugin migrated to package:web, meaning that it now supports WASM! + +Plugin now requires the following: +- Flutter >=3.19.0 +- Dart >=3.3.0 +- compileSDK 34 for Android part +- Java 17 for Android part +- Gradle 8.4 for Android part + +- **BREAKING** **FEAT**(battery_plus): Migrate to package:web ([#2720](https://github.com/fluttercommunity/plus_plugins/issues/2720)). ([21ccfa45](https://github.com/fluttercommunity/plus_plugins/commit/21ccfa459fcfb0609da46299fed6e10c9e77332b)) +- **BREAKING** **BUILD**(battery_plus): Target Java 17 on Android ([#2727](https://github.com/fluttercommunity/plus_plugins/issues/2727)). ([ca2c35ab](https://github.com/fluttercommunity/plus_plugins/commit/ca2c35abc464b26e741ace6e53e319dfa674b630)) +- **BREAKING** **BUILD**(battery_plus): Update to target and compile SDK 34 ([#2702](https://github.com/fluttercommunity/plus_plugins/pull/2702)). ([fc59745](https://github.com/fluttercommunity/plus_plugins/commit/fc59745d0a8650cc32f6e4d949887c4cdbffe547)) +- **BREAKING** **REFACTOR**(battery_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2592](https://github.com/fluttercommunity/plus_plugins/issues/2592)). ([fe07964b](https://github.com/fluttercommunity/plus_plugins/commit/fe07964b03997db73f22f3c30b7d09ea2c0adc93)) + - **FIX**(battery_plus): Add iOS Privacy Info ([#2580](https://github.com/fluttercommunity/plus_plugins/issues/2580)). ([9f36a001](https://github.com/fluttercommunity/plus_plugins/commit/9f36a0018daa08e3f3ebb59cebcd4149fae7c4bc)) + +## 5.0.3 + + - **FIX**(battery_plus): battery state always unknown on iOS ([#2481](https://github.com/fluttercommunity/plus_plugins/issues/2481)). ([ea892fb9](https://github.com/fluttercommunity/plus_plugins/commit/ea892fb96d06dcd685fa7953a468c377cc133ecc)) + +## 5.0.2 + + - **FIX**(battery_plus): Return correct state enum value on Android for not charging state ([#2451](https://github.com/fluttercommunity/plus_plugins/issues/2451)). ([68ddda39](https://github.com/fluttercommunity/plus_plugins/commit/68ddda39f0fa8e7ac950c13721403d49d0d97a65)) + +## 5.0.1 + +> Note: This release has breaking changes. There is a new state for battery available on Android, MacOS and Linux platforms. +> Also, MacOS implementation was updated to provide more accurate battery status. Be sure to test if it affects your MacOS app. + + - **BREAKING** **FIX**(battery_plus): Implement not_charging battery state ([#2275](https://github.com/fluttercommunity/plus_plugins/issues/2275)). ([6595e035](https://github.com/fluttercommunity/plus_plugins/commit/6595e035fd113b4a75651c9d471cc098d5798de3)) + - **BREAKING** **FEAT**(battery_plus): Introduce connected_not_charging state on MacOS ([#2399](https://github.com/fluttercommunity/plus_plugins/issues/2399)). ([78f44bf4](https://github.com/fluttercommunity/plus_plugins/commit/78f44bf41a7e8349240bacae2dd70598ba22e97a)) + - **BREAKING** **FEAT**(battery_plus): Introduce not_charging state on Linux ([#2400](https://github.com/fluttercommunity/plus_plugins/issues/2400)). ([42ef02bd](https://github.com/fluttercommunity/plus_plugins/commit/42ef02bd6de219fef1b2d9db2eebe9775a6ac751)) + - **DOCS**(battery_plus): Improve documentation on battery states ([#2402](https://github.com/fluttercommunity/plus_plugins/issues/2402)). ([baeb886f](https://github.com/fluttercommunity/plus_plugins/commit/baeb886fcc587f72662ce177ab4922496bb1db46)) + - **BREAKING** **FIX**(battery_plus): Bump iOS min target to 12 and update example app ([#2401](https://github.com/fluttercommunity/plus_plugins/issues/2401)). ([25ef7928](https://github.com/fluttercommunity/plus_plugins/commit/25ef7928cd57ca17d6107ed839711ea166d451a6)) + +## 5.0.0 + +This release was retracted due to due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). + +## 4.1.0 + +> Info: This release is a replacement for release 5.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. + + - **FIX**(battery_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2257](https://github.com/fluttercommunity/plus_plugins/issues/2257)). ([f5244e36](https://github.com/fluttercommunity/plus_plugins/commit/f5244e368c74d8b6e7bdd0062a4a2250dcabe540)) + - **FIX**(battery_plus): Revert bump of compileSDK to 34 ([#2228](https://github.com/fluttercommunity/plus_plugins/issues/2228)). ([e834f582](https://github.com/fluttercommunity/plus_plugins/commit/e834f582b85d5fb5a18aefc49b11b039ae600c78)) + - **FEAT**(battery_plus): Remove deprecated VALID_ARCHS iOS property ([#2025](https://github.com/fluttercommunity/plus_plugins/issues/2025)). ([09318317](https://github.com/fluttercommunity/plus_plugins/commit/0931831758dfc829e5649d880a616840a9b1d21f)) + +## 4.0.2 + + - **FIX**(battery_plus): Regenerate iOS and MacOS example apps ([#1873](https://github.com/fluttercommunity/plus_plugins/issues/1873)). ([18deeff3](https://github.com/fluttercommunity/plus_plugins/commit/18deeff3c68f312e2dae0de80273e1991ef97f45)) + - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) + +## 4.0.1 + + - **FIX**(battery_plus): Use ContextCompat on Android to register broadcast receiver ([#1811](https://github.com/fluttercommunity/plus_plugins/issues/1811)). ([b901615c](https://github.com/fluttercommunity/plus_plugins/commit/b901615cdc12d4bc5140ba9713d16f5a85fa6198)) + - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) + - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) + +## 4.0.0 + +> Note: This release has breaking changes. + + - **CHORE**(battery_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 + - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. + - **BREAKING** **CHORE**(battery_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1783). + - **REFACTOR**(battery_plus): Update example app to use Material 3. + - **FIX**(battery_plus): Close StreamController on Web and Linux when done (#1744). + +## 3.0.6 + + - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). + +## 3.0.5 + + - **FIX**(battery_plus): Huawei power save mode check (#1708). + - **FIX**(battery_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1700). + +## 3.0.4 + + - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). + - **FIX**(all): Fix depreciations for flutter 3.7 and 2.19 dart (#1529). + +## 3.0.3 + + - **FIX**: broadcast stream (#1479). + - **DOCS**: Updates for READMEs and website pages (#1389). + +## 3.0.2 + + - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). + +## 3.0.1 + + - **FIX**: lint warnings - add missing dependency for tests (#1233). + +## 3.0.0 + +> Note: This release has breaking changes. + + - **BREAKING** **REFACTOR**: platform implementation refactor into a single package (#1169). + +## 2.2.2 + + - **FIX**: batteryState always return unknown on API < 26 (#1120). + +## 2.2.1 + +- Fix: batteryState always return unknown on API < 26 + +## 2.2.0 + +- Android: Migrate to Kotlin +- Android: Bump targetSDK to 33 (Android 13) +- Android: Update dependencies, build config updates +- Update Flutter dependencies + +## 2.1.4+1 + +- Add issue_tracker link. + +## 2.1.4 + +- Update flutter_lints to 2.0.1 +- Update dev dependencies + +## 2.1.3 + +- Update battery_plus_linux dependency +- Set min Flutter version to 1.20.0 for all platforms + +## 2.1.2 + +- Fix embedding issue in example +- (Android) Update Kotlin and Gradle plugin + +## 2.1.1 + +- (Android) Fix null pointer exception in `isInBatterySaveMode()` on Samsung devices with One UI + +## 2.1.0 + +- Add batteryState getter + +## 2.0.2 + +- Update Flutter dependencies + +## 2.0.1 + +- Upgrade Android compile SDK version +- Several code improvements + +## 2.0.0 + +- Remove deprecated method `registerWith` (of Android v1 embedding) + +## 1.2.0 + +- migrate integration_test to flutter sdk + +## 1.1.1 + +- Fix: Add break statements for unknown battery state in Android and iOS implementations + +## 1.1.0 + +- Android, iOS, Windows : add getter for power save mode state + +## 1.0.2 + +- Android: migrate to mavenCentral + +## 1.0.1 + +- Improve documentation + +## 1.0.0 + +- Migrate to null safety + +## 0.10.1 + +- Address pub score + +## 0.10.0 + +- Added "unknown" battery state for batteryless systems. + +## 0.9.1 + +- Send initial battery status for Android + +## 0.9.0 + +- Add Linux support (`battery_plus_linux`) +- Add macOS support (`battery_plus_macos`) +- Add Windows support (`battery_plus_windows`) +- Rename method channel to avoid conflicts + +## 0.8.0 + +- Transfer to plus-plugins monorepo + +## 0.7.0 + +- Battery Plus supports web. + +## 0.6.0 + +- Implement Battery Plus based on new `BatteryPlatformInterface`. + +## 0.5.4 + +- Transfer package to Flutter Community under new name `batter_plus`. + +## 0.5.3 + +- Update package:e2e to use package:integration_test + +## 0.5.2 + +- Update package:e2e reference to use the local version in the flutter/plugins + repository. + +## 0.4.1 + +- Update lower bound of dart dependency to 2.1.0. + +## 0.3.1+10 + +- Update minimum Flutter version to 1.12.13+hotfix.5 +- Fix CocoaPods podspec lint warnings. + +## 0.3.1+9 + +- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). + +## 0.3.1+8 + +- Make the pedantic dev_dependency explicit. + +## 0.3.1+7 + +- Clean up various Android workarounds no longer needed after framework v1.12. + +## 0.3.1+6 + +- Remove the deprecated `author:` field from pubspec.yaml +- Migrate the plugin to the pubspec platforms manifest. +- Require Flutter SDK 1.10.0 or greater. + +## 0.3.1+5 + +- Fix pedantic linter errors. + +## 0.3.1+4 + +- Update and migrate iOS example project. + +## 0.3.1+3 + +- Remove AndroidX warning. + +## 0.3.1+2 + +- Include lifecycle dependency as a compileOnly one on Android to resolve + potential version conflicts with other transitive libraries. + +## 0.3.1+1 + +- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. + +## 0.3.1 + +- Support the v2 Android embedder. + +## 0.3.0+6 + +- Define clang module for iOS. + +## 0.3.0+5 + +- Fix Gradle version. + +## 0.3.0+4 + +- Update Dart code to conform to current Dart formatter. + +## 0.3.0+3 + +- Fix `batteryLevel` usage example in README + +## 0.3.0+2 + +- Bump the minimum Flutter version to 1.2.0. +- Add template type parameter to `invokeMethod` calls. + +## 0.3.0+1 + +- Log a more detailed warning at build time about the previous AndroidX + migration. + +## 0.3.0 + +- **Breaking change**. Migrate from the deprecated original Android Support + Library to AndroidX. This shouldn't result in any functional changes, but it + requires any Android apps using this plugin to [also + migrate](https://developer.android.com/jetpack/androidx/migrate) if they're + using the original support library. + +## 0.2.3 + +- Updated mockito dependency to 3.0.0 to get Dart 2 support. +- Update test package dependency to 1.3.0, and fixed tests to match. + +## 0.2.2 + +- Updated Gradle tooling to match Android Studio 3.1.2. + +## 0.2.1 + +- Fixed Dart 2 type error. +- Removed use of deprecated parameter in example. + +## 0.2.0 + +- **Breaking change**. Set SDK constraints to match the Flutter beta release. + +## 0.1.1 + +- Fixed warnings from the Dart 2.0 analyzer. +- Simplified and upgraded Android project template to Android SDK 27. +- Updated package description. + +## 0.1.0 + +- **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin + 3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in + order to use this version of the plugin. Instructions can be found + [here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1). + +## 0.0.2 + +- Add FLT prefix to iOS types. + +## 0.0.1+1 + +- Updated README + +## 0.0.1 + +- Initial release diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/LICENSE new file mode 100755 index 00000000..7b995420 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/LICENSE @@ -0,0 +1,27 @@ +Copyright 2017 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/README.md new file mode 100755 index 00000000..6dfef1f8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/README.md @@ -0,0 +1,56 @@ +# battery_plus + +[![pub package](https://img.shields.io/pub/v/battery_plus.svg)](https://pub.dev/packages/battery_plus) +[![pub points](https://img.shields.io/pub/points/battery_plus?color=2E8B57&label=pub%20points)](https://pub.dev/packages/battery_plus/score) +[![battery_plus](https://github.com/fluttercommunity/plus_plugins/actions/workflows/battery_plus.yaml/badge.svg)](https://github.com/fluttercommunity/plus_plugins/actions/workflows/battery_plus.yaml) + +[](https://flutter.dev/docs/development/packages-and-plugins/favorites) + +A Flutter plugin to access various information about the battery of the device the app is running on. + +## Platform Support + +| Android | iOS | MacOS | Web | Linux | Windows | +| :-----: | :-: | :---: | :-: | :---: | :----: | +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | + +## Requirements + +- Flutter >=3.19.0 +- Dart >=3.3.0 <4.0.0 +- iOS >=12.0 +- MacOS >=10.14 +- Android `compileSDK` 34 +- Java 17 +- Android Gradle Plugin >=8.3.0 +- Gradle wrapper >=8.4 + +## Usage + +Add `battery_plus` as a dependency in your pubspec.yaml file. + +### Example + +```dart +// Import package +import 'package:battery_plus/battery_plus.dart'; + +// Instantiate it +var battery = Battery(); + +// Access current battery level +print(await battery.batteryLevel); + +// Be informed when the state (full, charging, discharging) changes +battery.onBatteryStateChanged.listen((BatteryState state) { + // Do something with new state +}); + +// Check if device in battery save mode +// Currently available on Android, iOS and Windows platforms only +print(await battery.isInBatterySaveMode); +``` + +## Learn more + +- [API Documentation](https://pub.dev/documentation/battery_plus/latest/battery_plus/battery_plus-library.html) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/build.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/build.gradle new file mode 100755 index 00000000..c7c0c92c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/build.gradle @@ -0,0 +1,53 @@ +group 'dev.fluttercommunity.plus.battery' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.7.22' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.3.1' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdk 34 + + namespace 'dev.fluttercommunity.plus.battery' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = 17 + } + + defaultConfig { + minSdk 19 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + lintOptions { + disable 'InvalidPackage' + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation "androidx.core:core-ktx:1.13.1" +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle.properties new file mode 100755 index 00000000..8bd86f68 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle/wrapper/gradle-wrapper.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..fce403e4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/settings.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/settings.gradle new file mode 100755 index 00000000..ca0ecf2b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'battery_plus' diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/AndroidManifest.xml new file mode 100755 index 00000000..da40a4e7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt new file mode 100755 index 00000000..f7618902 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/android/src/main/kotlin/dev/fluttercommunity/plus/battery/BatteryPlusPlugin.kt @@ -0,0 +1,219 @@ +package dev.fluttercommunity.plus.battery + +import android.annotation.SuppressLint +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.plugin.common.EventChannel +import io.flutter.embedding.engine.plugins.FlutterPlugin +import android.content.Context +import android.content.BroadcastReceiver +import io.flutter.plugin.common.MethodChannel +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding +import io.flutter.plugin.common.MethodCall +import android.os.Build.VERSION_CODES +import io.flutter.plugin.common.EventChannel.EventSink +import android.content.IntentFilter +import android.content.Intent +import android.os.BatteryManager +import android.os.Build.VERSION +import android.content.ContextWrapper +import android.os.Build +import java.util.Locale +import android.os.PowerManager +import android.provider.Settings +import androidx.annotation.RequiresApi +import androidx.core.content.ContextCompat +import androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED + + +/** BatteryPlusPlugin */ +class BatteryPlusPlugin : MethodCallHandler, EventChannel.StreamHandler, FlutterPlugin { + private var applicationContext: Context? = null + private var chargingStateChangeReceiver: BroadcastReceiver? = null + private var methodChannel: MethodChannel? = null + private var eventChannel: EventChannel? = null + + override fun onAttachedToEngine(binding: FlutterPluginBinding) { + this.applicationContext = binding.applicationContext + methodChannel = MethodChannel(binding.binaryMessenger, "dev.fluttercommunity.plus/battery") + eventChannel = EventChannel(binding.binaryMessenger, "dev.fluttercommunity.plus/charging") + eventChannel!!.setStreamHandler(this) + methodChannel!!.setMethodCallHandler(this) + } + + override fun onDetachedFromEngine(binding: FlutterPluginBinding) { + applicationContext = null + methodChannel!!.setMethodCallHandler(null) + methodChannel = null + eventChannel!!.setStreamHandler(null) + eventChannel = null + } + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + when (call.method) { + "getBatteryLevel" -> { + val currentBatteryLevel = getBatteryLevel() + if (currentBatteryLevel != -1) { + result.success(currentBatteryLevel) + } else { + result.error("UNAVAILABLE", "Battery level not available.", null) + } + } + + "getBatteryState" -> { + val currentBatteryStatus = getBatteryStatus() + if (currentBatteryStatus != null) { + result.success(currentBatteryStatus) + } else { + result.error("UNAVAILABLE", "Charging status not available.", null) + } + } + + "isInBatterySaveMode" -> { + val isInPowerSaveMode = isInPowerSaveMode() + if (isInPowerSaveMode != null) { + result.success(isInPowerSaveMode) + } else { + result.error("UNAVAILABLE", "Battery save mode not available.", null) + } + } + + else -> result.notImplemented() + } + } + + @SuppressLint("WrongConstant") // Error in ContextCompat for RECEIVER_NOT_EXPORTED + override fun onListen(arguments: Any?, events: EventSink) { + chargingStateChangeReceiver = createChargingStateChangeReceiver(events) + applicationContext?.let { + ContextCompat.registerReceiver( + it, chargingStateChangeReceiver, + IntentFilter(Intent.ACTION_BATTERY_CHANGED), RECEIVER_NOT_EXPORTED + ) + } + val status = getBatteryStatus() + publishBatteryStatus(events, status) + } + + override fun onCancel(arguments: Any?) { + applicationContext!!.unregisterReceiver(chargingStateChangeReceiver) + chargingStateChangeReceiver = null + } + + private fun getBatteryStatus(): String? { + val status: Int = if (VERSION.SDK_INT >= VERSION_CODES.O) { + getBatteryProperty(BatteryManager.BATTERY_PROPERTY_STATUS) + } else { + val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + intent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1) ?: -1 + } + return convertBatteryStatus(status) + } + + private fun getBatteryLevel(): Int { + return if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + getBatteryProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) + } else { + val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) + val level = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) + val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1) + (level * 100 / scale) + } + } + + private fun isInPowerSaveMode(): Boolean? { + val deviceManufacturer = Build.MANUFACTURER.lowercase(Locale.getDefault()) + + return if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + when (deviceManufacturer) { + "xiaomi" -> isXiaomiPowerSaveModeActive() + "huawei" -> isHuaweiPowerSaveModeActive() + "samsung" -> isSamsungPowerSaveModeActive() + else -> checkPowerServiceSaveMode() + } + } else { + null + } + } + + private fun isSamsungPowerSaveModeActive(): Boolean { + val mode = Settings.System.getString(applicationContext!!.contentResolver, POWER_SAVE_MODE_SAMSUNG_NAME) + return if (mode == null && VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { + checkPowerServiceSaveMode() + } else { + mode == POWER_SAVE_MODE_SAMSUNG_VALUE + } + } + + @RequiresApi(VERSION_CODES.LOLLIPOP) + private fun isHuaweiPowerSaveModeActive(): Boolean { + val mode = Settings.System.getInt(applicationContext!!.contentResolver, POWER_SAVE_MODE_HUAWEI_NAME, -1) + return if (mode != -1) { + mode == POWER_SAVE_MODE_HUAWEI_VALUE + } else { + // On Devices like the P30 lite, we always get an -1 result code. + // Stackoverflow issue: https://stackoverflow.com/a/70500770 + checkPowerServiceSaveMode() + } + } + + private fun isXiaomiPowerSaveModeActive(): Boolean? { + val mode = Settings.System.getInt(applicationContext!!.contentResolver, POWER_SAVE_MODE_XIAOMI_NAME, -1) + return if (mode != -1) { + mode == POWER_SAVE_MODE_XIAOMI_VALUE + } else { + null + } + } + + @RequiresApi(api = VERSION_CODES.LOLLIPOP) + private fun checkPowerServiceSaveMode(): Boolean { + val powerManager = + applicationContext!!.getSystemService(Context.POWER_SERVICE) as PowerManager + return powerManager.isPowerSaveMode + } + + @RequiresApi(api = VERSION_CODES.LOLLIPOP) + private fun getBatteryProperty(property: Int): Int { + val batteryManager = applicationContext!!.getSystemService(Context.BATTERY_SERVICE) as BatteryManager + return batteryManager.getIntProperty(property) + } + + private fun createChargingStateChangeReceiver(events: EventSink): BroadcastReceiver { + return object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1) + publishBatteryStatus(events, convertBatteryStatus(status)) + } + } + } + + private fun convertBatteryStatus(status: Int): String? { + return when (status) { + BatteryManager.BATTERY_STATUS_CHARGING -> "charging" + BatteryManager.BATTERY_STATUS_FULL -> "full" + BatteryManager.BATTERY_STATUS_DISCHARGING -> "discharging" + BatteryManager.BATTERY_STATUS_NOT_CHARGING -> "connected_not_charging" + BatteryManager.BATTERY_STATUS_UNKNOWN -> "unknown" + else -> null + } + } + + private fun publishBatteryStatus(events: EventSink, status: String?) { + if (status != null) { + events.success(status) + } else { + events.error("UNAVAILABLE", "Charging status unavailable", null) + } + } + + companion object { + private const val POWER_SAVE_MODE_SAMSUNG_NAME = "psm_switch" + private const val POWER_SAVE_MODE_SAMSUNG_VALUE = "1" + + private const val POWER_SAVE_MODE_XIAOMI_NAME = "POWER_SAVE_MODE_OPEN" + private const val POWER_SAVE_MODE_XIAOMI_VALUE = 1 + + private const val POWER_SAVE_MODE_HUAWEI_NAME = "SmartModeStatus" + private const val POWER_SAVE_MODE_HUAWEI_VALUE = 4 + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/README.md new file mode 100755 index 00000000..9dc0c13e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/README.md @@ -0,0 +1,5 @@ +# battery_plus_example + +Demonstrates how to use the [battery_plus plugin][1] + +[1]: ../ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/build.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/build.gradle new file mode 100755 index 00000000..52b4b072 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/build.gradle @@ -0,0 +1,67 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + compileSdk 34 + + namespace 'io.flutter.plugins.batteryexample.example' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = 17 + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "io.flutter.plugins.batteryexample.example" + minSdk 21 + targetSdk 34 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + 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.debug + } + } +} + +flutter { + source '../..' +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/debug/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/debug/AndroidManifest.xml new file mode 100755 index 00000000..f094cef4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/AndroidManifest.xml new file mode 100755 index 00000000..dd87ee3a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/kotlin/io/flutter/plugins/batteryexample/example/MainActivity.kt b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/kotlin/io/flutter/plugins/batteryexample/example/MainActivity.kt new file mode 100755 index 00000000..f1c91930 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/kotlin/io/flutter/plugins/batteryexample/example/MainActivity.kt @@ -0,0 +1,5 @@ +package io.flutter.plugins.batteryexample.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/drawable/launch_background.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100755 index 00000000..304732f8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100755 index 00000000..db77bb4b Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100755 index 00000000..17987b79 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100755 index 00000000..09d43914 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100755 index 00000000..d5f1c8d3 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100755 index 00000000..4d6372ee Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/values/styles.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/values/styles.xml new file mode 100755 index 00000000..1f83a33f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/profile/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/profile/AndroidManifest.xml new file mode 100755 index 00000000..f094cef4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/build.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/build.gradle new file mode 100755 index 00000000..bc157bd1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle.properties new file mode 100755 index 00000000..d9cf55df --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..825c34f1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Oct 05 14:03:03 CEST 2021 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/settings.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/settings.gradle new file mode 100755 index 00000000..fa3b4d08 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/android/settings.gradle @@ -0,0 +1,25 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.3.1" apply false + id "org.jetbrains.kotlin.android" version "1.9.23" apply false +} + +include ":app" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/integration_test/battery_plus_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/integration_test/battery_plus_test.dart new file mode 100755 index 00000000..41a500e7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/integration_test/battery_plus_test.dart @@ -0,0 +1,40 @@ +// Copyright 2020, the Chromium authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +import 'dart:io'; + +import 'package:battery_plus/battery_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + final bool batteryLevelIsImplemented = + Platform.isAndroid || Platform.isMacOS || Platform.isLinux; + final bool batteryStateIsImplemented = Platform.isAndroid || + Platform.isIOS || + Platform.isMacOS || + Platform.isWindows || + Platform.isLinux; + final bool isInBatterySaveModeIsImplemented = + Platform.isAndroid || Platform.isIOS || Platform.isWindows; + + /// Throws [PlatformException] on iOS simulator and Windows. + /// Run on Android only. + testWidgets('Can get battery level', (WidgetTester tester) async { + final batteryLevel = await Battery().batteryLevel; + expect(batteryLevel, isNotNull); + }, skip: !batteryLevelIsImplemented); + + testWidgets('Can get battery state', (WidgetTester tester) async { + final batteryState = await Battery().batteryState; + expect(batteryState, isNotNull); + }, skip: !batteryStateIsImplemented); + + testWidgets('Can get if device is in battery save mode', + (WidgetTester tester) async { + final isInBatterySaveMode = await Battery().isInBatterySaveMode; + expect(isInBatterySaveMode, false); + }, skip: !isInBatterySaveModeIsImplemented); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/AppFrameworkInfo.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100755 index 00000000..9625e105 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Debug.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Debug.xcconfig new file mode 100755 index 00000000..ec97fc6f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Release.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Release.xcconfig new file mode 100755 index 00000000..c4855bfe --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.pbxproj b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..f983bf7a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,721 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97AE7F1E32AA538C368FCC3F /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D432E8EDF62A8247198B1CAB /* Pods_RunnerTests.framework */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + D698218E8DD3B8EB846F3847 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B57435E320EDA8EA441D43AF /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4CAB07678B2F77AE275A0BEC /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 50957247B576084F0771E61F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 650E23DC8A7DFC99D7539C89 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 75FBB03C676F0D043B4369C7 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 7AF090DBA22B5ED51CC286D2 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B57435E320EDA8EA441D43AF /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D432E8EDF62A8247198B1CAB /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F41590C41B15A335C8248CA6 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D698218E8DD3B8EB846F3847 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FC2D413132B4BF4DF093FCCB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 97AE7F1E32AA538C368FCC3F /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 5BA506C21DC982245BC4307C /* Pods */ = { + isa = PBXGroup; + children = ( + 650E23DC8A7DFC99D7539C89 /* Pods-Runner.debug.xcconfig */, + 50957247B576084F0771E61F /* Pods-Runner.release.xcconfig */, + F41590C41B15A335C8248CA6 /* Pods-Runner.profile.xcconfig */, + 75FBB03C676F0D043B4369C7 /* Pods-RunnerTests.debug.xcconfig */, + 7AF090DBA22B5ED51CC286D2 /* Pods-RunnerTests.release.xcconfig */, + 4CAB07678B2F77AE275A0BEC /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 5FC27932B351D2B369512AAA /* Frameworks */ = { + isa = PBXGroup; + children = ( + B57435E320EDA8EA441D43AF /* Pods_Runner.framework */, + D432E8EDF62A8247198B1CAB /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + 5BA506C21DC982245BC4307C /* Pods */, + 5FC27932B351D2B369512AAA /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 2475DCCE7D4FDE42E0DECD43 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + FC2D413132B4BF4DF093FCCB /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + DEE2275EA4B4ABAF40CF9EB0 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 3785BB9002D6BDCD15832A60 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2475DCCE7D4FDE42E0DECD43 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3785BB9002D6BDCD15832A60 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + DEE2275EA4B4ABAF40CF9EB0 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 75FBB03C676F0D043B4369C7 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AF090DBA22B5ED51CC286D2 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4CAB07678B2F77AE275A0BEC /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..919434a6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..e42adcb3 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/AppDelegate.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/AppDelegate.swift new file mode 100755 index 00000000..70693e4a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..d36b1fab --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100755 index 00000000..dc9ada47 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100755 index 00000000..7353c41e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100755 index 00000000..6ed2d933 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100755 index 00000000..4cd7b009 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100755 index 00000000..fe730945 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100755 index 00000000..321773cd Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100755 index 00000000..502f463a Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100755 index 00000000..e9f5fea2 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100755 index 00000000..84ac32ae Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100755 index 00000000..8953cba0 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100755 index 00000000..0467bf12 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100755 index 00000000..0bedcf2f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100755 index 00000000..89c2725b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 00000000..f2e259c7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/Main.storyboard b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100755 index 00000000..f3c28516 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Info.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Info.plist new file mode 100755 index 00000000..d5a7c08f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Battery Plus Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + battery_plus_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Runner-Bridging-Header.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Runner-Bridging-Header.h new file mode 100755 index 00000000..308a2a56 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/RunnerTests/RunnerTests.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..86a7c3b1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/lib/main.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/lib/main.dart new file mode 100755 index 00000000..a6f34822 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/lib/main.dart @@ -0,0 +1,145 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:battery_plus/battery_plus.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + useMaterial3: true, + colorSchemeSeed: const Color(0x9f4376f8), + ), + home: const MyHomePage(), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key}); + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + final Battery _battery = Battery(); + + BatteryState? _batteryState; + StreamSubscription? _batteryStateSubscription; + + @override + void initState() { + super.initState(); + _battery.batteryState.then(_updateBatteryState); + _batteryStateSubscription = + _battery.onBatteryStateChanged.listen(_updateBatteryState); + } + + void _updateBatteryState(BatteryState state) { + if (_batteryState == state) return; + setState(() { + _batteryState = state; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Battery plus example app'), + elevation: 4, + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'Current battery state:', + style: TextStyle(fontSize: 24), + ), + const SizedBox(height: 8), + Text( + '${_batteryState?.name}', + style: const TextStyle(fontSize: 24), + ), + const SizedBox(height: 24), + ElevatedButton( + onPressed: () { + _battery.batteryLevel.then( + (batteryLevel) { + showDialog( + context: context, + builder: (_) => AlertDialog( + content: Text('Battery: $batteryLevel%'), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text('OK'), + ) + ], + ), + ); + }, + ); + }, + child: const Text('Get battery level'), + ), + const SizedBox(height: 24), + ElevatedButton( + onPressed: () { + _battery.isInBatterySaveMode.then( + (isInPowerSaveMode) { + showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text( + 'Is in Battery Save mode?', + style: TextStyle(fontSize: 20), + ), + content: Text( + "$isInPowerSaveMode", + style: const TextStyle(fontSize: 18), + ), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text('Close'), + ) + ], + ), + ); + }, + ); + }, + child: const Text('Is in Battery Save mode?'), + ) + ], + ), + ), + ); + } + + @override + void dispose() { + super.dispose(); + if (_batteryStateSubscription != null) { + _batteryStateSubscription!.cancel(); + } + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/CMakeLists.txt new file mode 100755 index 00000000..386893d7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "io.flutter.plugins.batteryexample.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..5b465c7e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/main.cc b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/main.cc new file mode 100755 index 00000000..8bc15615 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/main.cc @@ -0,0 +1,11 @@ +#include "my_application.h" + +int main(int argc, char **argv) { + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); + + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.cc b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.cc new file mode 100755 index 00000000..cef2f771 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.cc @@ -0,0 +1,45 @@ +#include "my_application.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication *application) { + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +static void my_application_class_init(MyApplicationClass *klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; +} + +static void my_application_init(MyApplication *self) {} + +MyApplication *my_application_new() { + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.h new file mode 100755 index 00000000..3258a73c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication *my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Debug.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100755 index 00000000..4b81f9b2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Release.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100755 index 00000000..5caa9d15 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.pbxproj b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..9e9505e8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,791 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 093D643C82D4B7EE630E0DE2 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB44BF446D4E3EDCD5B77BA3 /* Pods_Runner.framework */; }; + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 90893944B3704A3D4ED269F2 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6AE51C6475BCF9D909943E1 /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* battery_plus_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = battery_plus_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 3BD291780B1536D56E3D8614 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 49893D8393C2F92741388488 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 58313ABA94CF9296393DDC88 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 58950022FA3EF51275C04A8A /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + A6AE51C6475BCF9D909943E1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B872A381CB0689F35D462D2B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + CB44BF446D4E3EDCD5B77BA3 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E95D25412347C218A8EAE4BA /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 90893944B3704A3D4ED269F2 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 093D643C82D4B7EE630E0DE2 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 9F06F6A0F47185C443DA9499 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* battery_plus_example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + 9F06F6A0F47185C443DA9499 /* Pods */ = { + isa = PBXGroup; + children = ( + 49893D8393C2F92741388488 /* Pods-Runner.debug.xcconfig */, + 3BD291780B1536D56E3D8614 /* Pods-Runner.release.xcconfig */, + B872A381CB0689F35D462D2B /* Pods-Runner.profile.xcconfig */, + E95D25412347C218A8EAE4BA /* Pods-RunnerTests.debug.xcconfig */, + 58313ABA94CF9296393DDC88 /* Pods-RunnerTests.release.xcconfig */, + 58950022FA3EF51275C04A8A /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CB44BF446D4E3EDCD5B77BA3 /* Pods_Runner.framework */, + A6AE51C6475BCF9D909943E1 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + F2FDA1BE1872CC09A966504C /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 4C38364606CE0024B21D00BA /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 86E7C6C5AB4A292BD51729FA /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* battery_plus_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1430; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 4C38364606CE0024B21D00BA /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 86E7C6C5AB4A292BD51729FA /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F2FDA1BE1872CC09A966504C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E95D25412347C218A8EAE4BA /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/battery_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/battery_plus_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 58313ABA94CF9296393DDC88 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/battery_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/battery_plus_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 58950022FA3EF51275C04A8A /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/battery_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/battery_plus_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..15041ed5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/AppDelegate.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/AppDelegate.swift new file mode 100755 index 00000000..d53ef643 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..a2ec33f1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "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" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100755 index 00000000..82b6f9d9 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100755 index 00000000..13b35eba Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100755 index 00000000..0a3f5fa4 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100755 index 00000000..bdb57226 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100755 index 00000000..f083318e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100755 index 00000000..326c0e72 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100755 index 00000000..2f1632cf Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Base.lproj/MainMenu.xib b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100755 index 00000000..80e867a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/AppInfo.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100755 index 00000000..2f815b1f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = battery_plus_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.batteryInfoPlus.example + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 io.flutter.plugins. All rights reserved. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Debug.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Debug.xcconfig new file mode 100755 index 00000000..36b0fd94 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Release.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Release.xcconfig new file mode 100755 index 00000000..dff4f495 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Warnings.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100755 index 00000000..42bcbf47 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/DebugProfile.entitlements b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/DebugProfile.entitlements new file mode 100755 index 00000000..dddb8a30 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Info.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Info.plist new file mode 100755 index 00000000..4789daa6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/MainFlutterWindow.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/MainFlutterWindow.swift new file mode 100755 index 00000000..3cc05eb2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Release.entitlements b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Release.entitlements new file mode 100755 index 00000000..852fa1a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/RunnerTests/RunnerTests.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..5418c9f5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/pubspec.yaml new file mode 100755 index 00000000..bcdf8703 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/pubspec.yaml @@ -0,0 +1,23 @@ +name: battery_plus_example +description: Demonstrates how to use the battery_plus plugin. + +environment: + sdk: '>=3.3.0 <4.0.0' + flutter: '>=3.19.0' + +dependencies: + flutter: + sdk: flutter + battery_plus: ^6.0.3 + +dev_dependencies: + flutter_driver: + sdk: flutter + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + flutter_lints: ^4.0.0 + +flutter: + uses-material-design: true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/test/widget_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/test/widget_test.dart new file mode 100755 index 00000000..0ca91e79 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/test/widget_test.dart @@ -0,0 +1,19 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter_test/flutter_test.dart'; + +import 'package:battery_plus_example/main.dart'; + +void main() { + testWidgets('Initial battery value smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + expect(find.text('null'), findsOneWidget); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/favicon.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/favicon.png new file mode 100755 index 00000000..8aaa46ac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/favicon.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-192.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-192.png new file mode 100755 index 00000000..b749bfef Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-192.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-512.png b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-512.png new file mode 100755 index 00000000..88cfd48d Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/icons/Icon-512.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/index.html b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/index.html new file mode 100755 index 00000000..a0c14606 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/manifest.json b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/manifest.json new file mode 100755 index 00000000..8c012917 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/CMakeLists.txt new file mode 100755 index 00000000..abf90408 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.15) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..744f08a9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,102 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..977e38b5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/Runner.rc b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/Runner.rc new file mode 100755 index 00000000..9b0221d3 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "io.flutter.plugins.batteryexample" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2020 io.flutter.plugins.batteryexample. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..0f0105d9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.cpp @@ -0,0 +1,64 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opporutunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..69234d4f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/flutter_window.h @@ -0,0 +1,39 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "run_loop.h" +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { +public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + virtual ~FlutterWindow(); + +protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + +private: + // The run loop driving events for this window. + RunLoop *run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/main.cpp new file mode 100755 index 00000000..fc17fec6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/main.cpp @@ -0,0 +1,36 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resource.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resources/app_icon.ico b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/resources/app_icon.ico differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.cpp new file mode 100755 index 00000000..31b89f62 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.cpp @@ -0,0 +1,66 @@ +#include "run_loop.h" + +#include + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto instance : flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.h new file mode 100755 index 00000000..7fe1aacc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/run_loop.h @@ -0,0 +1,38 @@ +#ifndef RUNNER_RUN_LOOP_H_ +#define RUNNER_RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { +public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const &) = delete; + RunLoop &operator=(RunLoop const &) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + +private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUNNER_RUN_LOOP_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/runner.exe.manifest b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.cpp new file mode 100755 index 00000000..37501e5d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.cpp @@ -0,0 +1,22 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.h new file mode 100755 index 00000000..7021e6d0 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/utils.h @@ -0,0 +1,8 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..9669d7fc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.cpp @@ -0,0 +1,236 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { +public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + +private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar *instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; + +const wchar_t *WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size) { + Destroy(); + + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window *that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.h new file mode 100755 index 00000000..7b518125 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/example/windows/runner/win32_window.h @@ -0,0 +1,95 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { +public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.h new file mode 100755 index 00000000..5c205f90 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.h @@ -0,0 +1,8 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface FPPBatteryPlusPlugin : NSObject +@end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.m b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.m new file mode 100755 index 00000000..3f755e4b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/Classes/FPPBatteryPlusPlugin.m @@ -0,0 +1,121 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "FPPBatteryPlusPlugin.h" + +@interface FPPBatteryPlusPlugin () +@end + +@implementation FPPBatteryPlusPlugin { + FlutterEventSink _eventSink; +} + ++ (void)registerWithRegistrar:(NSObject *)registrar { + FPPBatteryPlusPlugin *instance = [[FPPBatteryPlusPlugin alloc] init]; + + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/battery" + binaryMessenger:[registrar messenger]]; + + [registrar addMethodCallDelegate:instance channel:channel]; + FlutterEventChannel *chargingChannel = [FlutterEventChannel + eventChannelWithName:@"dev.fluttercommunity.plus/charging" + binaryMessenger:[registrar messenger]]; + [chargingChannel setStreamHandler:instance]; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call + result:(FlutterResult)result { + if ([@"getBatteryLevel" isEqualToString:call.method]) { + int batteryLevel = [self getBatteryLevel]; + if (batteryLevel == -1) { + result([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Battery info unavailable" + details:nil]); + } else { + result(@(batteryLevel)); + } + } else if ([@"getBatteryState" isEqualToString:call.method]) { + NSString *state = [self getBatteryState]; + if (state) { + result(state); + } else { + result([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Charging status unavailable" + details:nil]); + } + } else if ([@"isInBatterySaveMode" isEqualToString:call.method]) { + result(@([[NSProcessInfo processInfo] isLowPowerModeEnabled])); + } else { + result(FlutterMethodNotImplemented); + } +} + +- (void)onBatteryStateDidChange:(NSNotification *)notification { + [self sendBatteryStateEvent]; +} + +- (void)sendBatteryStateEvent { + if (!_eventSink) + return; + NSString *state = [self getBatteryState]; + if (state) { + _eventSink(state); + } else { + _eventSink([FlutterError errorWithCode:@"UNAVAILABLE" + message:@"Charging status unavailable" + details:nil]); + } +} + +- (NSString *)getBatteryState { + UIDevice *device = UIDevice.currentDevice; + device.batteryMonitoringEnabled = YES; + UIDeviceBatteryState state = [device batteryState]; + switch (state) { + case UIDeviceBatteryStateUnknown: + return @"unknown"; + case UIDeviceBatteryStateFull: + return @"full"; + case UIDeviceBatteryStateCharging: + return @"charging"; + case UIDeviceBatteryStateUnplugged: + return @"discharging"; + default: + return nil; + } +} + +- (int)getBatteryLevel { + UIDevice *device = UIDevice.currentDevice; + device.batteryMonitoringEnabled = YES; + if (device.batteryState == UIDeviceBatteryStateUnknown) { + return -1; + } else { + return ((int)(device.batteryLevel * 100)); + } +} + +#pragma mark FlutterStreamHandler impl + +- (FlutterError *)onListenWithArguments:(id)arguments + eventSink:(FlutterEventSink)eventSink { + _eventSink = eventSink; + [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES]; + [self sendBatteryStateEvent]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(onBatteryStateDidChange:) + name:UIDeviceBatteryStateDidChangeNotification + object:nil]; + return nil; +} + +- (FlutterError *)onCancelWithArguments:(id)arguments { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + _eventSink = nil; + return nil; +} + +@end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/PrivacyInfo.xcprivacy b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/PrivacyInfo.xcprivacy new file mode 100755 index 00000000..a34b7e2e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/battery_plus.podspec b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/battery_plus.podspec new file mode 100755 index 00000000..39c05510 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/ios/battery_plus.podspec @@ -0,0 +1,24 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'battery_plus' + s.version = '1.0.0' + s.summary = 'Flutter plugin for accessing information about the battery_plus.' + s.description = <<-DESC +A Flutter plugin to access various information about the battery of the device the app is running on. +Downloaded by pub (not CocoaPods). + DESC + s.homepage = 'https://plus.fluttercommunity.dev/' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Community Team' => 'authors@fluttercommunity.dev' } + s.source = { :http => 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus' } + s.documentation_url = 'https://pub.dev/packages/battery_plus' + s.source_files = 'Classes/**/*' + s.public_header_files = 'Classes/**/*.h' + s.dependency 'Flutter' + + s.platform = :ios, '12.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.resource_bundles = {'batery_plus_privacy' => ['PrivacyInfo.xcprivacy']} +end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/battery_plus.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/battery_plus.dart new file mode 100755 index 00000000..0ffaff6a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/battery_plus.dart @@ -0,0 +1,56 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; + +export 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart' + show BatteryState; + +export 'src/battery_plus_linux.dart'; + +/// API for accessing information about the battery of the device the Flutter app is running on. +class Battery { + /// Constructs a singleton instance of [Battery]. + /// + /// [Battery] is designed to work as a singleton. + // When a second instance is created, the first instance will not be able to listen to the + // EventChannel because it is overridden. Forcing the class to be a singleton class can prevent + // misuse of creating a second instance from a programmer. + factory Battery() { + _singleton ??= Battery._(); + return _singleton!; + } + + Battery._(); + + static Battery? _singleton; + + static BatteryPlatform get _platform { + return BatteryPlatform.instance; + } + + /// get battery level + Future get batteryLevel { + return _platform.batteryLevel; + } + + /// check if device is on battery save mode + /// + /// Currently only implemented on Android, iOS and Windows. + Future get isInBatterySaveMode { + return _platform.isInBatterySaveMode; + } + + /// Get battery state + Future get batteryState { + return _platform.batteryState; + } + + /// Fires whenever the battery state changes. + Stream get onBatteryStateChanged { + return _platform.onBatteryStateChanged; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_linux.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_linux.dart new file mode 100755 index 00000000..89ab9b77 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_linux.dart @@ -0,0 +1,98 @@ +import 'dart:async'; + +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; +import 'package:meta/meta.dart'; +import 'package:upower/upower.dart'; + +extension _ToBatteryState on UPowerDeviceState { + BatteryState toBatteryState() { + switch (this) { + case UPowerDeviceState.charging: + return BatteryState.charging; + + case UPowerDeviceState.discharging: + case UPowerDeviceState.pendingDischarge: + return BatteryState.discharging; + + case UPowerDeviceState.fullyCharged: + return BatteryState.full; + + case UPowerDeviceState.pendingCharge: + return BatteryState.connectedNotCharging; + + default: + return BatteryState.unknown; + } + } +} + +/// +@visibleForTesting +typedef UPowerClientFactory = UPowerClient Function(); + +/// The Linux implementation of BatteryPlatform. +class BatteryPlusLinuxPlugin extends BatteryPlatform { + /// Register this dart class as the platform implementation for linux + static void registerWith() { + BatteryPlatform.instance = BatteryPlusLinuxPlugin(); + } + + /// Returns the current battery level in percent. + @override + Future get batteryLevel { + final client = createClient(); + return client + .connect() + .then((_) => client.displayDevice.percentage.round()) + .whenComplete(() => client.close()); + } + + /// Returns the current battery state. + @override + Future get batteryState { + final client = createClient(); + return client + .connect() + .then((_) => client.displayDevice.state.toBatteryState()) + .whenComplete(() => client.close); + } + + /// Fires whenever the battery state changes. + @override + Stream get onBatteryStateChanged { + _stateController ??= StreamController.broadcast( + onListen: _startListenState, + onCancel: _stopListenState, + ); + return _stateController!.stream.asBroadcastStream(); + } + + UPowerClient? _stateClient; + StreamController? _stateController; + + @visibleForTesting + // ignore: public_member_api_docs, prefer_function_declarations_over_variables + UPowerClientFactory createClient = () => UPowerClient(); + + void _addState(UPowerDeviceState value) { + _stateController!.add(value.toBatteryState()); + } + + Future _startListenState() async { + _stateClient ??= createClient(); + await _stateClient! + .connect() + .then((_) => _addState(_stateClient!.displayDevice.state)); + _stateClient!.displayDevice.propertiesChanged.listen((properties) { + if (properties.contains('State')) { + _addState(_stateClient!.displayDevice.state); + } + }); + } + + void _stopListenState() { + _stateController?.close(); + _stateClient?.close(); + _stateClient = null; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_web.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_web.dart new file mode 100755 index 00000000..f179ad28 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/lib/src/battery_plus_web.dart @@ -0,0 +1,107 @@ +import 'dart:async'; +import 'dart:js_interop'; + +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:web/web.dart'; + +/// The web implementation of the BatteryPlatform of the Battery plugin. +/// +/// The Battery Status API is not supported by Firefox and Safari. +/// Therefore, when using this plugin, recommend that test not only in Chrome but also in Firefox and Safari. +/// In some environments, accessing this plugin from Firefox or Safari will cause unexpected exception. +/// If an unexpected Exception occurs, try-catch at the point where the method is being called. +class BatteryPlusWebPlugin extends BatteryPlatform { + /// Constructs a BatteryPlusPlugin. + BatteryPlusWebPlugin(); + + /// Return [BatteryManager] if the BatteryManager API is supported by the User Agent. + Future _getBatteryManager() async { + try { + return await window.navigator.getBattery().toDart; + } on NoSuchMethodError catch (_) { + // BatteryManager API is not supported this User Agent. + return null; + } on Object catch (_) { + // Unexpected exception occurred. + return null; + } + } + + /// Factory method that initializes the Battery plugin platform with an instance + /// of the plugin for the web. + static void registerWith(Registrar registrar) { + BatteryPlatform.instance = BatteryPlusWebPlugin(); + } + + /// Returns the current battery level in percent. + @override + Future get batteryLevel async { + final batteryManager = await _getBatteryManager(); + if (batteryManager == null) { + return 0; + } + + // level is a number representing the system's battery charge level scaled to a value between 0.0 and 1.0 + final level = batteryManager.level; + return (level * 100).toInt(); + } + + /// Returns the current battery state. + @override + Future get batteryState async { + final batteryManager = await _getBatteryManager(); + if (batteryManager == null) { + return BatteryState.unknown; + } + + return _checkBatteryChargingState(batteryManager.charging); + } + + StreamController? _batteryChangeStreamController; + Stream? _batteryChange; + + /// Returns a Stream of BatteryState changes. + @override + Stream get onBatteryStateChanged async* { + final batteryManager = await _getBatteryManager(); + if (batteryManager == null) { + yield BatteryState.unknown; + return; + } + + if (_batteryChange != null) { + yield* _batteryChange!; + return; + } + + _batteryChangeStreamController = StreamController(); + _batteryChangeStreamController?.add( + _checkBatteryChargingState(batteryManager.charging), + ); + + batteryManager.onchargingchange = (Event _) { + _batteryChangeStreamController?.add( + _checkBatteryChargingState(batteryManager.charging), + ); + }.toJS; + + _batteryChangeStreamController?.onCancel = () { + _batteryChangeStreamController?.close(); + + _batteryChangeStreamController = null; + _batteryChange = null; + }; + + _batteryChange = _batteryChangeStreamController!.stream.asBroadcastStream(); + yield* _batteryChange!; + } + + BatteryState _checkBatteryChargingState(bool charging) { + if (charging) { + return BatteryState.charging; + } else { + return BatteryState.discharging; + } + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusChargingHandler.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusChargingHandler.swift new file mode 100755 index 00000000..902fc75b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusChargingHandler.swift @@ -0,0 +1,87 @@ +import Foundation +import FlutterMacOS + +class BatteryPlusChargingHandler: NSObject, FlutterStreamHandler { + + private var context: Int = 0 + + private var source: CFRunLoopSource? + private var runLoop: CFRunLoop? + private var eventSink: FlutterEventSink? + + func onListen(withArguments arguments: Any?, eventSink event: @escaping FlutterEventSink) -> FlutterError? { + self.eventSink = event + start() + return nil + } + + func onCancel(withArguments arguments: Any?) -> FlutterError? { + stop() + self.eventSink = nil + return nil + } + + func start() { + // If there is an added loop, we remove it before adding a new one. + stop() + + // Gets the initial battery status + let initialStatus = getBatteryStatus() + if let sink = self.eventSink { + sink(initialStatus) + } + + // Registers a run loop which is notified when the battery status changes + let context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()) + source = IOPSNotificationCreateRunLoopSource({ (context) in + let _self = Unmanaged.fromOpaque(UnsafeRawPointer(context!)).takeUnretainedValue() + let status = _self.getBatteryStatus() + print(status) + if let sink = _self.eventSink { + sink(status) + } + }, context).takeUnretainedValue() + + // Adds loop to source + runLoop = RunLoop.current.getCFRunLoop() + CFRunLoopAddSource(runLoop, source, .defaultMode) + } + + func stop() { + guard let runLoop = runLoop, let source = source else { + return + } + CFRunLoopRemoveSource(runLoop, source, .defaultMode) + } + + func getBatteryStatus()-> String { + let powerSourceSnapshot = IOPSCopyPowerSourcesInfo().takeRetainedValue() + let sources = IOPSCopyPowerSourcesList(powerSourceSnapshot).takeRetainedValue() as [CFTypeRef] + + // When no sources available it is highly likely a desktop, thus, connected_not_charging. + if sources.isEmpty { + return "connected_not_charging" + } + + let description = IOPSGetPowerSourceDescription(powerSourceSnapshot, sources[0]).takeUnretainedValue() as! [String: AnyObject] + + if let isFullyCharged = description[kIOPSIsChargedKey] as? Bool { + if isFullyCharged { + return "full" + } + } + + let isConnected = (description[kIOPSPowerSourceStateKey] as? String) + + if let isCharging = (description[kIOPSIsChargingKey] as? Bool) { + if isCharging { + return "charging" + } else if isConnected == kIOPSACPowerValue { + return "connected_not_charging" + } else { + return "discharging" + } + } + return "UNAVAILABLE" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusMacosPlugin.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusMacosPlugin.swift new file mode 100755 index 00000000..246336c0 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/Classes/BatteryPlusMacosPlugin.swift @@ -0,0 +1,65 @@ +import Cocoa +import FlutterMacOS +import IOKit.ps + +public class BatteryPlusMacosPlugin: NSObject, FlutterPlugin { + private var chargingHandler: BatteryPlusChargingHandler + + init(chargingHandler: BatteryPlusChargingHandler) { + self.chargingHandler = chargingHandler + super.init() + } + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "dev.fluttercommunity.plus/battery", binaryMessenger: registrar.messenger) + + let eventChannel = FlutterEventChannel(name: "dev.fluttercommunity.plus/charging", binaryMessenger: registrar.messenger) + + let chargingHandler = BatteryPlusChargingHandler() + + let instance = BatteryPlusMacosPlugin(chargingHandler: chargingHandler) + registrar.addMethodCallDelegate(instance, channel: channel) + + eventChannel.setStreamHandler(chargingHandler) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getBatteryLevel": + handleGetBatteryLevelMethodCall(result) + case "getBatteryState": + handleGetBatteryStateMethodCall(result) + default: + result(FlutterMethodNotImplemented) + } + } + + private func handleGetBatteryLevelMethodCall(_ result: FlutterResult){ + let level = getBatteryLevel() + if(level != -1){ + result(level) + + } else { + result("UNAVAILABLE") + } + + } + + private func getBatteryLevel()-> Int { + let powerSourceSnapshot = IOPSCopyPowerSourcesInfo().takeRetainedValue() + let sources = IOPSCopyPowerSourcesList(powerSourceSnapshot).takeRetainedValue() as Array + if sources.isEmpty { + return -1 + } + let description = IOPSGetPowerSourceDescription(powerSourceSnapshot, sources[0]).takeUnretainedValue() as! [String: AnyObject] + if let currentCapacity = description[kIOPSCurrentCapacityKey] as? Int { + return currentCapacity; + } + return -1 + } + + private func handleGetBatteryStateMethodCall(_ result: FlutterResult){ + let state = self.chargingHandler.getBatteryStatus() + result(state); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/battery_plus.podspec b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/battery_plus.podspec new file mode 100755 index 00000000..7f715df7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/macos/battery_plus.podspec @@ -0,0 +1,22 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint battery_plus_macos.podspec' to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'battery_plus' + s.version = '0.0.1' + s.summary = 'Flutter Battery Plus' + s.description = <<-DESC +A Flutter plugin for accessing information about the battery state(full, charging, discharging). + DESC + s.homepage = 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus' + s.license = { :file => '../LICENSE' } + s.author = { 'Flutter Community' => 'authors@fluttercommunity.dev' } + s.source = { :path => 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus' } + s.source_files = 'Classes/**/*' + s.dependency 'FlutterMacOS' + + s.platform = :osx, '10.14' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.swift_version = '5.0' +end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/pubspec.yaml new file mode 100755 index 00000000..db772443 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/pubspec.yaml @@ -0,0 +1,49 @@ +name: battery_plus +description: Flutter plugin for accessing information about the battery state(full, charging, discharging). +version: 6.0.3 +homepage: https://github.com/fluttercommunity/plus_plugins +repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/battery_plus/battery_plus +issue_tracker: https://github.com/fluttercommunity/plus_plugins/labels/battery_plus +topics: + - battery + - utils + +flutter: + plugin: + platforms: + android: + package: dev.fluttercommunity.plus.battery + pluginClass: BatteryPlusPlugin + ios: + pluginClass: FPPBatteryPlusPlugin + linux: + dartPluginClass: BatteryPlusLinuxPlugin + macos: + pluginClass: BatteryPlusMacosPlugin + web: + pluginClass: BatteryPlusWebPlugin + fileName: src/battery_plus_web.dart + windows: + pluginClass: BatteryPlusWindowsPlugin + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + battery_plus_platform_interface: ^2.0.1 + meta: ^1.8.0 + upower: ^0.7.0 + web: ^1.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + async: ^2.10.0 + flutter_lints: ^4.0.0 + mockito: ^5.4.0 + plugin_platform_interface: ^2.1.4 + +environment: + sdk: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.dart new file mode 100755 index 00000000..7f86b691 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.dart @@ -0,0 +1,64 @@ +import 'package:battery_plus/src/battery_plus_linux.dart'; +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:upower/upower.dart'; + +import 'battery_plus_linux_test.mocks.dart'; + +@GenerateMocks([UPowerClient, UPowerDevice]) +void main() { + test('registered instance', () { + BatteryPlusLinuxPlugin.registerWith(); + expect(BatteryPlatform.instance, isA()); + }); + test('battery level', () async { + final battery = BatteryPlusLinuxPlugin(); + battery.createClient = () { + return createMockClient(percentage: 56.78); + }; + expect(battery.batteryLevel, completion(equals(57))); + }); + + test('battery state', () async { + final battery = BatteryPlusLinuxPlugin(); + battery.createClient = () { + return createMockClient(state: UPowerDeviceState.charging); + }; + expect(battery.batteryState, completion(BatteryState.charging)); + }); + + test('battery state changes', () { + final battery = BatteryPlusLinuxPlugin(); + battery.createClient = () { + final client = createMockClient(state: UPowerDeviceState.charging); + final device = client.displayDevice; + when(device.propertiesChanged).thenAnswer((_) { + when(device.state).thenReturn(UPowerDeviceState.fullyCharged); + return Stream.value(['State']); + }); + return client; + }; + expect(battery.onBatteryStateChanged.isBroadcast, isTrue); + expect(battery.onBatteryStateChanged, + emitsInOrder([BatteryState.charging, BatteryState.full])); + }); +} + +MockUPowerClient createMockClient({ + double? percentage, + UPowerDeviceState? state, +}) { + final device = MockUPowerDevice(); + if (percentage != null) { + when(device.percentage).thenReturn(percentage); + } + if (state != null) { + when(device.state).thenReturn(state); + } + + final client = MockUPowerClient(); + when(client.displayDevice).thenReturn(device); + return client; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.mocks.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.mocks.dart new file mode 100755 index 00000000..4d1a2e7d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_plus_linux_test.mocks.dart @@ -0,0 +1,245 @@ +// Mocks generated by Mockito 5.2.0 from annotations +// in battery_plus_linux/test/battery_plus_linux_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i3; + +import 'package:mockito/mockito.dart' as _i1; +import 'package:upower/src/upower_client.dart' as _i2; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types + +class _FakeUPowerKbdBacklight_0 extends _i1.Fake + implements _i2.UPowerKbdBacklight {} + +class _FakeUPowerDevice_1 extends _i1.Fake implements _i2.UPowerDevice {} + +/// A class which mocks [UPowerClient]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUPowerClient extends _i1.Mock implements _i2.UPowerClient { + MockUPowerClient() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.UPowerKbdBacklight get kbdBacklight => + (super.noSuchMethod(Invocation.getter(#kbdBacklight), + returnValue: _FakeUPowerKbdBacklight_0()) as _i2.UPowerKbdBacklight); + @override + set kbdBacklight(_i2.UPowerKbdBacklight? _kbdBacklight) => + super.noSuchMethod(Invocation.setter(#kbdBacklight, _kbdBacklight), + returnValueForMissingStub: null); + @override + String get daemonVersion => + (super.noSuchMethod(Invocation.getter(#daemonVersion), returnValue: '') + as String); + @override + bool get onBattery => + (super.noSuchMethod(Invocation.getter(#onBattery), returnValue: false) + as bool); + @override + bool get lidIsPresent => + (super.noSuchMethod(Invocation.getter(#lidIsPresent), returnValue: false) + as bool); + @override + bool get lidIsClosed => + (super.noSuchMethod(Invocation.getter(#lidIsClosed), returnValue: false) + as bool); + @override + List<_i2.UPowerDevice> get devices => + (super.noSuchMethod(Invocation.getter(#devices), + returnValue: <_i2.UPowerDevice>[]) as List<_i2.UPowerDevice>); + @override + _i2.UPowerDevice get displayDevice => + (super.noSuchMethod(Invocation.getter(#displayDevice), + returnValue: _FakeUPowerDevice_1()) as _i2.UPowerDevice); + @override + _i3.Stream<_i2.UPowerDevice> get deviceAdded => + (super.noSuchMethod(Invocation.getter(#deviceAdded), + returnValue: Stream<_i2.UPowerDevice>.empty()) + as _i3.Stream<_i2.UPowerDevice>); + @override + _i3.Stream<_i2.UPowerDevice> get deviceRemoved => + (super.noSuchMethod(Invocation.getter(#deviceRemoved), + returnValue: Stream<_i2.UPowerDevice>.empty()) + as _i3.Stream<_i2.UPowerDevice>); + @override + _i3.Stream> get propertiesChanged => (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: Stream>.empty()) as _i3.Stream>); + @override + _i3.Future connect() => + (super.noSuchMethod(Invocation.method(#connect, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future getCriticalAction() => + (super.noSuchMethod(Invocation.method(#getCriticalAction, []), + returnValue: Future.value('')) as _i3.Future); + @override + _i3.Future close() => (super.noSuchMethod(Invocation.method(#close, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); +} + +/// A class which mocks [UPowerDevice]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockUPowerDevice extends _i1.Mock implements _i2.UPowerDevice { + MockUPowerDevice() { + _i1.throwOnMissingStub(this); + } + + @override + String get nativePath => + (super.noSuchMethod(Invocation.getter(#nativePath), returnValue: '') + as String); + @override + String get vendor => + (super.noSuchMethod(Invocation.getter(#vendor), returnValue: '') + as String); + @override + String get model => + (super.noSuchMethod(Invocation.getter(#model), returnValue: '') + as String); + @override + String get serial => + (super.noSuchMethod(Invocation.getter(#serial), returnValue: '') + as String); + @override + int get updateTime => + (super.noSuchMethod(Invocation.getter(#updateTime), returnValue: 0) + as int); + @override + _i2.UPowerDeviceType get type => (super.noSuchMethod(Invocation.getter(#type), + returnValue: _i2.UPowerDeviceType.unknown) as _i2.UPowerDeviceType); + @override + bool get powerSupply => + (super.noSuchMethod(Invocation.getter(#powerSupply), returnValue: false) + as bool); + @override + bool get hasHistory => + (super.noSuchMethod(Invocation.getter(#hasHistory), returnValue: false) + as bool); + @override + bool get hasStatistics => + (super.noSuchMethod(Invocation.getter(#hasStatistics), returnValue: false) + as bool); + @override + bool get online => + (super.noSuchMethod(Invocation.getter(#online), returnValue: false) + as bool); + @override + double get energy => + (super.noSuchMethod(Invocation.getter(#energy), returnValue: 0.0) + as double); + @override + double get energyEmpty => + (super.noSuchMethod(Invocation.getter(#energyEmpty), returnValue: 0.0) + as double); + @override + double get energyFull => + (super.noSuchMethod(Invocation.getter(#energyFull), returnValue: 0.0) + as double); + @override + double get energyFullDesign => (super + .noSuchMethod(Invocation.getter(#energyFullDesign), returnValue: 0.0) + as double); + @override + double get energyRate => + (super.noSuchMethod(Invocation.getter(#energyRate), returnValue: 0.0) + as double); + @override + double get voltage => + (super.noSuchMethod(Invocation.getter(#voltage), returnValue: 0.0) + as double); + @override + double get luminosity => + (super.noSuchMethod(Invocation.getter(#luminosity), returnValue: 0.0) + as double); + @override + int get timeToEmpty => + (super.noSuchMethod(Invocation.getter(#timeToEmpty), returnValue: 0) + as int); + @override + int get timeToFull => + (super.noSuchMethod(Invocation.getter(#timeToFull), returnValue: 0) + as int); + @override + double get percentage => + (super.noSuchMethod(Invocation.getter(#percentage), returnValue: 0.0) + as double); + @override + double get temperature => + (super.noSuchMethod(Invocation.getter(#temperature), returnValue: 0.0) + as double); + @override + bool get isPresent => + (super.noSuchMethod(Invocation.getter(#isPresent), returnValue: false) + as bool); + @override + _i2.UPowerDeviceState get state => + (super.noSuchMethod(Invocation.getter(#state), + returnValue: _i2.UPowerDeviceState.unknown) as _i2.UPowerDeviceState); + @override + bool get isRechargeable => (super + .noSuchMethod(Invocation.getter(#isRechargeable), returnValue: false) + as bool); + @override + double get capacity => + (super.noSuchMethod(Invocation.getter(#capacity), returnValue: 0.0) + as double); + @override + _i2.UPowerDeviceTechnology get technology => + (super.noSuchMethod(Invocation.getter(#technology), + returnValue: _i2.UPowerDeviceTechnology.unknown) + as _i2.UPowerDeviceTechnology); + @override + _i2.UPowerDeviceWarningLevel get warningLevel => + (super.noSuchMethod(Invocation.getter(#warningLevel), + returnValue: _i2.UPowerDeviceWarningLevel.unknown) + as _i2.UPowerDeviceWarningLevel); + @override + _i2.UPowerDeviceBatteryLevel get batteryLevel => + (super.noSuchMethod(Invocation.getter(#batteryLevel), + returnValue: _i2.UPowerDeviceBatteryLevel.unknown) + as _i2.UPowerDeviceBatteryLevel); + @override + String get iconName => + (super.noSuchMethod(Invocation.getter(#iconName), returnValue: '') + as String); + @override + _i3.Stream> get propertiesChanged => (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: Stream>.empty()) as _i3.Stream>); + @override + _i3.Future refresh() => + (super.noSuchMethod(Invocation.method(#refresh, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future> getHistory( + String? type, int? resolution, {int? timespan = 0}) => + (super.noSuchMethod( + Invocation.method( + #getHistory, [type, resolution], {#timespan: timespan}), + returnValue: Future>.value( + <_i2.UPowerDeviceHistoryRecord>[])) + as _i3.Future>); + @override + _i3.Future> getStatistics( + String? type) => + (super.noSuchMethod(Invocation.method(#getStatistics, [type]), + returnValue: Future>.value( + <_i2.UPowerDeviceStatisticsRecord>[])) + as _i3.Future>); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_test.dart new file mode 100755 index 00000000..fb1a7683 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/test/battery_test.dart @@ -0,0 +1,66 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:async/async.dart'; +import 'package:battery_plus/battery_plus.dart'; +import 'package:battery_plus_platform_interface/battery_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +class MockBatteryPlatform + with MockPlatformInterfaceMixin + implements BatteryPlatform { + @override + Future get batteryLevel => Future.value(42); + + @override + Future get batteryState => Future.value(BatteryState.charging); + + @override + Stream get onBatteryStateChanged => Stream.fromIterable([ + BatteryState.unknown, + BatteryState.charging, + BatteryState.full, + BatteryState.discharging + ]); + + @override + Future get isInBatterySaveMode => Future.value(true); +} + +void main() { + late Battery battery; + late MockBatteryPlatform fakePlatform; + + setUpAll(() { + fakePlatform = MockBatteryPlatform(); + BatteryPlatform.instance = fakePlatform; + battery = Battery(); + }); + + test('batteryLevel', () async { + expect(await battery.batteryLevel, 42); + }); + + test('isInBatterySaveMode', () async { + expect(await battery.isInBatterySaveMode, true); + }); + + test('current state of the battery', () async { + expect(await battery.batteryState, BatteryState.charging); + }); + + test('receiving events of the battery state', () async { + final queue = StreamQueue(battery.onBatteryStateChanged); + + expect(await queue.next, BatteryState.unknown); + expect(await queue.next, BatteryState.charging); + expect(await queue.next, BatteryState.full); + expect(await queue.next, BatteryState.discharging); + + expect(await queue.hasNext, false); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/CMakeLists.txt new file mode 100755 index 00000000..b8f1d409 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.15) +set(PROJECT_NAME "battery_plus") +project(${PROJECT_NAME} LANGUAGES CXX) + +set(PLUGIN_NAME "${PROJECT_NAME}_plugin") + +add_library(${PLUGIN_NAME} SHARED + "${PLUGIN_NAME}.cpp" + "system_battery.cpp" +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) + +# List of absolute paths to libraries that should be bundled with the plugin +set(battery_plus_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/battery_plus_plugin.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/battery_plus_plugin.cpp new file mode 100755 index 00000000..868e5847 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/battery_plus_plugin.cpp @@ -0,0 +1,176 @@ +#include "include/battery_plus/battery_plus_windows_plugin.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "include/battery_plus/system_battery.h" + +namespace { + +typedef flutter::EventChannel FlEventChannel; +typedef flutter::EventSink FlEventSink; +typedef flutter::MethodCall FlMethodCall; +typedef flutter::MethodResult FlMethodResult; +typedef flutter::MethodChannel FlMethodChannel; +typedef flutter::StreamHandler FlStreamHandler; +typedef flutter::StreamHandlerError + FlStreamHandlerError; + +class BatteryPlusWindowsPlugin : public flutter::Plugin { +public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + + BatteryPlusWindowsPlugin(flutter::PluginRegistrarWindows *registrar); + ~BatteryPlusWindowsPlugin(); + +private: + void HandleMethodCall(const FlMethodCall &method_call, + std::unique_ptr result); + std::unique_ptr _methodChannel; + std::unique_ptr _eventChannel; +}; + +class BatteryStatusStreamHandler : public FlStreamHandler { +public: + BatteryStatusStreamHandler(flutter::PluginRegistrarWindows *registrar); + +protected: + void AddStatusEvent(BatteryStatus status); + + std::unique_ptr + OnListenInternal(const flutter::EncodableValue *arguments, + std::unique_ptr &&events) override; + + std::unique_ptr + OnCancelInternal(const flutter::EncodableValue *arguments) override; + +private: + int _delegate = -1; + SystemBattery _battery; + std::unique_ptr _events; + flutter::PluginRegistrarWindows *_registrar = nullptr; +}; + +void BatteryPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar) { + registrar->AddPlugin(std::make_unique(registrar)); +} + +BatteryPlusWindowsPlugin::BatteryPlusWindowsPlugin( + flutter::PluginRegistrarWindows *registrar) { + _methodChannel = std::make_unique( + registrar->messenger(), "dev.fluttercommunity.plus/battery", + &flutter::StandardMethodCodec::GetInstance()); + + _methodChannel->SetMethodCallHandler([this](const auto &call, auto result) { + HandleMethodCall(call, std::move(result)); + }); + + _eventChannel = std::make_unique( + registrar->messenger(), "dev.fluttercommunity.plus/charging", + &flutter::StandardMethodCodec::GetInstance()); + + _eventChannel->SetStreamHandler( + std::make_unique(registrar)); +} + +BatteryPlusWindowsPlugin::~BatteryPlusWindowsPlugin() {} + +BatteryStatusStreamHandler::BatteryStatusStreamHandler( + flutter::PluginRegistrarWindows *registrar) + : _registrar(registrar) {} + +void BatteryStatusStreamHandler::AddStatusEvent(BatteryStatus status) { + if (status != BatteryStatus::Error) { + _events->Success(_battery.GetStatusString()); + } else { + _events->Error(std::to_string(_battery.GetError()), + _battery.GetErrorString()); + } +} + +std::unique_ptr +BatteryStatusStreamHandler::OnListenInternal( + const flutter::EncodableValue *arguments, + std::unique_ptr &&events) { + _events = std::move(events); + + HWND hwnd = _registrar->GetView()->GetNativeWindow(); + BatteryStatusCallback callback = std::bind( + &BatteryStatusStreamHandler::AddStatusEvent, this, std::placeholders::_1); + + if (!_battery.StartListen(hwnd, callback)) { + return std::make_unique( + std::to_string(_battery.GetError()), _battery.GetErrorString(), + nullptr); + } + + _delegate = _registrar->RegisterTopLevelWindowProcDelegate( + [this](HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { + _battery.ProcessMsg(hwnd, message, wparam, lparam); + return std::nullopt; + }); + + AddStatusEvent(_battery.GetStatus()); + return nullptr; +} + +std::unique_ptr +BatteryStatusStreamHandler::OnCancelInternal( + const flutter::EncodableValue *arguments) { + _registrar->UnregisterTopLevelWindowProcDelegate(_delegate); + if (!_battery.StopListen()) { + return std::make_unique( + std::to_string(_battery.GetError()), _battery.GetErrorString(), + nullptr); + } + _delegate = -1; + _events.reset(); + return nullptr; +} + +void BatteryPlusWindowsPlugin::HandleMethodCall( + const FlMethodCall &method_call, std::unique_ptr result) { + if (method_call.method_name().compare("isInBatterySaveMode") == 0) { + SystemBattery battery; + int batteryStatus = battery.GetBatterySaveMode(); + if (batteryStatus == 0 || batteryStatus == 1) { + bool isBatteryMode = batteryStatus == 1; + result->Success(flutter::EncodableValue(isBatteryMode)); + } else { + result->Error(std::to_string(battery.GetError()), + battery.GetErrorString()); + } + } else if (method_call.method_name().compare("getBatteryLevel") == 0) { + SystemBattery battery; + int level = battery.GetLevel(); + if (level >= 0) { + result->Success(flutter::EncodableValue(level)); + } else { + result->Error(std::to_string(battery.GetError()), + battery.GetErrorString()); + } + } else if (method_call.method_name().compare("getBatteryState") == 0) { + SystemBattery battery; + result->Success(flutter::EncodableValue(battery.GetStatusString())); + } else { + result->NotImplemented(); + } +} + +} // namespace + +void BatteryPlusWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + BatteryPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h new file mode 100755 index 00000000..9d8d9226 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/battery_plus_windows_plugin.h @@ -0,0 +1,23 @@ +#ifndef FLUTTER_PLUGIN_BATTERY_PLUS_PLUGIN_H_ +#define FLUTTER_PLUGIN_BATTERY_PLUS_PLUGIN_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void BatteryPlusWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_PLUGIN_BATTERY_PLUS_WINDOWS_PLUGIN_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/system_battery.h b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/system_battery.h new file mode 100755 index 00000000..9e58f0e2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/include/battery_plus/system_battery.h @@ -0,0 +1,37 @@ +#ifndef FLUTTER_PLUGIN_BATTERY_PLUS_SYSTEM_BATTERY_H_ +#define FLUTTER_PLUGIN_BATTERY_PLUS_SYSTEM_BATTERY_H_ + +#include +#include + +#include +#include + +enum class BatteryStatus { Full, Charging, Discharging, Error, Unknown }; + +typedef std::function BatteryStatusCallback; + +class SystemBattery { +public: + SystemBattery(); + ~SystemBattery(); + + int GetBatterySaveMode() const; + int GetLevel() const; + + BatteryStatus GetStatus() const; + std::string GetStatusString() const; + + int GetError() const; + std::string GetErrorString() const; + + bool StartListen(HWND hwnd, BatteryStatusCallback callback); + void ProcessMsg(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); + bool StopListen(); + +private: + HPOWERNOTIFY _notifier = nullptr; + BatteryStatusCallback _callback = nullptr; +}; + +#endif // FLUTTER_PLUGIN_BATTERY_PLUS_SYSTEM_BATTERY_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/system_battery.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/system_battery.cpp new file mode 100755 index 00000000..b769196b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/battery_plus/windows/system_battery.cpp @@ -0,0 +1,125 @@ +#include "include/battery_plus/system_battery.h" + +#include + +namespace { +enum ACLineStatus { + Offline = 0, + Online = 1, +}; + +enum BatteryLevel { + Empty = 0, + Full = 100, + Unknown = 255, +}; + +enum BatteryFlag { + High = 1, // the battery capacity is at more than 66 percent + Low = 2, // the battery capacity is at less than 33 percent + Critical = 4, // the battery capacity is at less than five percent + Charging = 8, + NoBattery = 128 // no system battery +}; + +bool GetBatteryStatus(LPSYSTEM_POWER_STATUS lpStatus) { + return GetSystemPowerStatus(lpStatus) != 0; +} + +bool IsValidBatteryStatus(LPSYSTEM_POWER_STATUS lpStatus) { + return lpStatus->BatteryFlag != NoBattery && + lpStatus->BatteryLifePercent != Unknown; +} +} // namespace + +SystemBattery::SystemBattery() {} + +SystemBattery::~SystemBattery() { StopListen(); } + +int SystemBattery::GetBatterySaveMode() const { + SYSTEM_POWER_STATUS status; + if (!GetBatteryStatus(&status)) { + return -1; + } + return status.SystemStatusFlag; +} + +int SystemBattery::GetLevel() const { + SYSTEM_POWER_STATUS status; + if (!GetBatteryStatus(&status) || !IsValidBatteryStatus(&status)) { + return -1; + } + return status.BatteryLifePercent; +} + +BatteryStatus SystemBattery::GetStatus() const { + SYSTEM_POWER_STATUS status; + if (!GetBatteryStatus(&status)) { + return BatteryStatus::Error; + } + if (IsValidBatteryStatus(&status)) { + if (status.ACLineStatus == Online) { + if (status.BatteryLifePercent == Full) { + return BatteryStatus::Full; + } else if (status.BatteryFlag & Charging) { + return BatteryStatus::Charging; + } + } else if (status.ACLineStatus == Offline) { + if (!(status.BatteryFlag & Charging)) { + return BatteryStatus::Discharging; + } + } + } + return BatteryStatus::Unknown; +} + +std::string SystemBattery::GetStatusString() const { + switch (GetStatus()) { + case BatteryStatus::Charging: + return "charging"; + case BatteryStatus::Discharging: + return "discharging"; + case BatteryStatus::Full: + return "full"; + case BatteryStatus::Unknown: + default: + return "unknown"; + } +} + +int SystemBattery::GetError() const { return GetLastError(); } + +std::string SystemBattery::GetErrorString() const { + // ### TODO: FormatMessage() + return "GetSystemPowerStatus() failed"; +} + +bool SystemBattery::StartListen(HWND hwnd, BatteryStatusCallback callback) { + if (_notifier) { + return false; + } + _callback = callback; + _notifier = RegisterPowerSettingNotification(hwnd, &GUID_ACDC_POWER_SOURCE, + DEVICE_NOTIFY_WINDOW_HANDLE); + return _notifier != nullptr; +} + +void SystemBattery::ProcessMsg(HWND hwnd, UINT message, WPARAM wparam, + LPARAM lparam) { + if (!_callback) { + return; + } + if (message == WM_POWERBROADCAST && wparam == PBT_APMPOWERSTATUSCHANGE) { + _callback(GetStatus()); + } +} + +bool SystemBattery::StopListen() { + if (!_notifier) { + return false; + } + HPOWERNOTIFY notifier = nullptr; + std::swap(notifier, _notifier); + _callback = nullptr; + return UnregisterPowerSettingNotification(notifier) != 0; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus deleted file mode 120000 index 1dfc8a9a..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.0.5/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/CHANGELOG.md new file mode 100755 index 00000000..02a57c8d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/CHANGELOG.md @@ -0,0 +1,507 @@ +## 6.0.5 + + - **DOCS**(connectivity_plus): Update plugin requirements in README ([#3160](https://github.com/fluttercommunity/plus_plugins/issues/3160)). ([277f8b6b](https://github.com/fluttercommunity/plus_plugins/commit/277f8b6ba9ee6e7e5e3b1cce3e5eb8416830ba6b)) + +## 6.0.4 + + - **CHORE**(connectivity_plus): Use `>=0.5.0 < 2.0.0` version range for package:web. + - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) + - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) + +## 6.0.3 + + - **FIX**(connectivity_plus): Ensure Connectivity on Android is correctly reported when lost ([#2836](https://github.com/fluttercommunity/plus_plugins/issues/2836)). ([2aa6ad7a](https://github.com/fluttercommunity/plus_plugins/commit/2aa6ad7a1c05d35b894e6cef515bd9dfa49351dd)) + +## 6.0.2 + + - **REFACTOR**(connectivity_plus): remove ReachabilityConnectivityProvider and ReachabilitySwift dependency ([#2813](https://github.com/fluttercommunity/plus_plugins/issues/2813)). ([f9ad927f](https://github.com/fluttercommunity/plus_plugins/commit/f9ad927f5c18f8ed8d4c22a24476430239c13492)) + - **REFACTOR**(connectivity_plus): Migrate Android example to use the new plugins declaration ([#2771](https://github.com/fluttercommunity/plus_plugins/issues/2771)). ([04200c23](https://github.com/fluttercommunity/plus_plugins/commit/04200c2311e8dd581980ed19f8ebd24d0afd1512)) + - **FIX**(connectivity_plus): WASM-compatible conditional imports ([#2825](https://github.com/fluttercommunity/plus_plugins/issues/2825)). ([6bee4a7e](https://github.com/fluttercommunity/plus_plugins/commit/6bee4a7e02d681ce94d8bd95c4399d844b0ceb27)) + - **FIX**(connectivity_plus): Improve iOS PathMonitorConnectivityProvider implementation and documentation ([#2763](https://github.com/fluttercommunity/plus_plugins/issues/2763)). ([c850d58e](https://github.com/fluttercommunity/plus_plugins/commit/c850d58ed9f422182c8f77583a43bcb13d5d979f)) + - **DOCS**(connectivity_plus): Document supported ConnectivityResult per platform ([#2780](https://github.com/fluttercommunity/plus_plugins/issues/2780)). ([1c4aec01](https://github.com/fluttercommunity/plus_plugins/commit/1c4aec019e74433a2b1174d75522b5abb0c9d9b4)) + - **DOCS**(connectivity_plus): Update README for more clarity ([#2770](https://github.com/fluttercommunity/plus_plugins/issues/2770)). ([8fb738e2](https://github.com/fluttercommunity/plus_plugins/commit/8fb738e2b8f5534db8f1c0fbbeae1a51cf03d099)) + - **DOCS**(connectivity_plus): Specify behavior when there is no connectivity ([#2753](https://github.com/fluttercommunity/plus_plugins/issues/2753)). ([8f132a23](https://github.com/fluttercommunity/plus_plugins/commit/8f132a23a0424299c5e9b946171164bc66710540)) + - **DOCS**(connectivity_plus): Improve documentation onConnectivityChanged method ([#2746](https://github.com/fluttercommunity/plus_plugins/issues/2746)). ([9ea21fbd](https://github.com/fluttercommunity/plus_plugins/commit/9ea21fbdbb9974077375f803f5bb3c57abcb6488)) + +## 6.0.1 + +> Note: This release has breaking changes. + +> Plugin now requires the following: +> - Flutter >=3.19.0 +> - Dart >=3.3.0 +> - compileSDK 34 for Android part +> - Java 17 for Android part +> - Gradle 8.4 for Android part + +In this release plugin migrated to package:web, meaning that it now supports WASM! + +- **BREAKING** **FEAT**(connectivity_plus): support multiple connectivity types at the same time ([#2599](https://github.com/fluttercommunity/plus_plugins/issues/2599)). ([5b477468](https://github.com/fluttercommunity/plus_plugins/commit/5b4774683d6e186fbd69cf4208302221f52aa54d)) +- **BREAKING** **FEAT**(connectivity_plus): Migrate to package:web ([#2621](https://github.com/fluttercommunity/plus_plugins/issues/2621)). ([fbc8e61c](https://github.com/fluttercommunity/plus_plugins/commit/fbc8e61c4f8996d6ba47622de191a83dc2fe1882)) +- **BREAKING** **BUILD**(connectivity_plus): Target Java 17 on Android ([2413e45e](https://github.com/fluttercommunity/plus_plugins/commit/2413e45e88fa6a431c29f8e6240780e20c405453)) +- **BREAKING** **BUILD**(connectivity_plus): Update to target and compile SDK 34 ([#2701](https://github.com/fluttercommunity/plus_plugins/pull/2701)). ([7ddd749](https://github.com/fluttercommunity/plus_plugins/commit/7ddd74989d2921af706f5e7a1aa32e41159ce13f)) +- **BREAKING** **REFACTOR**(connectivity_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2588](https://github.com/fluttercommunity/plus_plugins/issues/2588)). ([f6fe62d5](https://github.com/fluttercommunity/plus_plugins/commit/f6fe62d5f4d87c93e0f974e96bbd47ff453937d9)) +- **FIX**(connectivity_plus): Emit event with types on Android when subscribing to onConnectivityChanged ([#2721](https://github.com/fluttercommunity/plus_plugins/issues/2721)). ([5a81e7ef](https://github.com/fluttercommunity/plus_plugins/commit/5a81e7ef75d75852935f7a095e5b426d534edff9)) +- **FIX**(connectivity_plus): Fix connectivity state update on Android when network is lost ([#2673](https://github.com/fluttercommunity/plus_plugins/issues/2673)). ([21191682](https://github.com/fluttercommunity/plus_plugins/commit/2119168267e436e5900ea09cf68dd110e51b01e0)) +- **FIX**(connectivity_plus): Return valid connection type when only one available ([#2668](https://github.com/fluttercommunity/plus_plugins/issues/2668)). ([81026a4c](https://github.com/fluttercommunity/plus_plugins/commit/81026a4c6c07cb610299a8f17db69c518475a675)) +- **FIX**(connectivity_plus): Add iOS Privacy Info ([#2581](https://github.com/fluttercommunity/plus_plugins/issues/2581)). ([707fab70](https://github.com/fluttercommunity/plus_plugins/commit/707fab70eb1dd262226158be97586a67eec03dd0)) +- **FIX**(connectivity_plus): Fix iOS example app name ([#2722](https://github.com/fluttercommunity/plus_plugins/issues/2722)). ([2441accd](https://github.com/fluttercommunity/plus_plugins/commit/2441accdffc3bc86f5e74db6c682d0dd4fbd6813)) +- **DOCS**(connectivity_plus): Update documentation to address API changes ([#2719](https://github.com/fluttercommunity/plus_plugins/issues/2719)). ([59b9b341](https://github.com/fluttercommunity/plus_plugins/commit/59b9b3417cd0387d8a5f9e857eb350b4048dc68c)) + +## 6.0.0 + +> Note: DO NOT USE THIS RELEASE. It is invalid due to a publishing issue + +## 5.0.2 + + - **FIX**(connectivity_plus): Return correct connection state on Linux ([#2371](https://github.com/fluttercommunity/plus_plugins/issues/2371)). ([26576d83](https://github.com/fluttercommunity/plus_plugins/commit/26576d838be3b39121fd77ab33f49fc1fff1a97f)) + +## 5.0.1 + + - **FIX**(connectivity_plus): Fix CHANGELOG to not mention Kotlin requirement ([#2246](https://github.com/fluttercommunity/plus_plugins/issues/2246)). ([e489d4aa](https://github.com/fluttercommunity/plus_plugins/commit/e489d4aa7a223b152b89b6c33ae994e8a73679bd)) + +## 5.0.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FIX**(connectivity_plus): Bump min iOS to 12 to not crash after builds with Xcode 15 ([#2169](https://github.com/fluttercommunity/plus_plugins/issues/2169)). ([cf7d93fb](https://github.com/fluttercommunity/plus_plugins/commit/cf7d93fbfc76830acf2db755543cf4235a49df60)) + - **FIX**(connectivity_plus): Revert bump compileSDK to 34 ([#2229](https://github.com/fluttercommunity/plus_plugins/issues/2229)). ([01df65ce](https://github.com/fluttercommunity/plus_plugins/commit/01df65ce0268093de5dd381c84d251668dc95984)) + - **FEAT**(connectivity_plus): Remove deprecated VALID_ARCHS iOS property ([#2021](https://github.com/fluttercommunity/plus_plugins/issues/2021)). ([ee89d583](https://github.com/fluttercommunity/plus_plugins/commit/ee89d5836c7e598fce07d89e82a2d127ddfacbf8)) + + +## 4.0.2 + + - **FIX**(connectivity_plus): Downgrade js version to work with Flutter 3.3.10 ([#1989](https://github.com/fluttercommunity/plus_plugins/issues/1989)). ([42938c0c](https://github.com/fluttercommunity/plus_plugins/commit/42938c0c03132f7f50fa047c2970660d2720d320)) + - **FIX**(connectivity_plus): Regenerate iOS and MacOS example apps ([#1874](https://github.com/fluttercommunity/plus_plugins/issues/1874)). ([fc22e54e](https://github.com/fluttercommunity/plus_plugins/commit/fc22e54ec166d37d4326a9271677054fd34ccc3c)) + - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) + +## 4.0.1 + + - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) + +## 4.0.0 + +> Note: This release has breaking changes. + + - **CHORE**(connectivity_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 + - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. + - **BREAKING** **CHORE**(connectivity_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1782). + +## 3.0.6 + + - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). + +## 3.0.5 + + - **FIX**(connectivity_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1701). + +## 3.0.4 + + - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). + - **DOCS**(connectivity_plus): Documentation added for the missing network interface enums (#1524). + +## 3.0.3 + + - **FIX**: Do not return ConnectivityResult.none on iOS and MacOS with VPN (#1335). + - **DOCS**: Updates for READMEs and website pages (#1389). + +## 3.0.2 + + - **FIX**: Add connectivity_plus_web export (#1278). + +## 3.0.1 + + - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). + +## 3.0.0 + +> Note: This release has breaking changes. + + - **FIX**: lint warnings - add missing dependency for tests (#1233). + - **BREAKING** **REFACTOR**: two-package federated architecture (#1227). + +## 2.3.9 + + - **CHORE**: Version tagging using melos. + +## 2.3.8 + +- Discard unused warnings for `ensurePathMonitor` & `ensureReachability` call in iOS. + +## 2.3.7 + +- iOS: Reduce compiler warnings + +## 2.3.6+1 + +- Add issue_tracker link. + +## 2.3.6 + +- Web: Fix Bad state: Stream has already been listened to (#943) + +## 2.3.5 + +- Stop sending events once flutter engine detached on iOS/macOS (#865) + +## 2.3.4 + +- Disables internal use of `NetworkInformationAPI` which is still experimental + +## 2.3.3 + +- macOS: Send events on main thread + +## 2.3.2 + +- iOS: Send events on main thread (#846) + +## 2.3.1 + +- Update flutter_lints to 2.0.1 +- Update dev dependencies + +## 2.3.0 + +- Add iOS ConnectivityProvider based on NWPathMonitor for iOS 12+. + +## 2.2.2 + +- Reachability.swift ".unavailable" for iOS is deprecated. + +## 2.2.1 + +- Bump `nm` plugin to 0.5.0 (connectivity_plus_linux) +- Fix embedding issue in example + +## 2.2.0 + +- Add bluetooth as connectivity result. Supported on Android, Linux, and Web + +## 2.1.0 + +- Migrated iOS plugin to Swift +- Removed dependency to old Reachability pod +- Added dependency to Reachability.swift pod + +## 2.0.3 + +- Add Gradle wrapper to Android plugin + +## 2.0.2 + +- Fix for error: lambda expressions are not supported in -source 7 + +## 2.0.1 + +- Upgrade Android compile SDK version +- Several code improvements + +## 2.0.0 + +- Remove deprecated method `registerWith` (of Android v1 embedding) + +## 1.4.0 + +- [MacOS]: Backport to macOS 10.11 + +## 1.3.0 + +- Add ethernet as connectivity result. Supported on Android, iOS, Windows, Linux, macOS, and Web + +## 1.2.0 + +- migrate integration_test to flutter sdk + +## 1.1.0 + +- Add ethernet as connectivity result. Supported on Android, Linux, macOS, and Web + +## 1.0.8 + +- Web: Fix to show `ConnectivityResult.mobile` instead of `ConnectivityResult.wifi` when the network is connected to 4g + +## 1.0.7 + +- Android: Fix to detect no-network when Wi-Fi is disconnected on Android M and above + +## 1.0.6 + +- Android: Fix unregisterReceiver call for API < N + +## 1.0.5 + +- Android: Fix memory leak from registered receiver +- Android: Fix gradle crash due to previous update in version 1.0.4 + +## 1.0.4 + +- Android: Add explicit compiler version to avoid warnings + +## 1.0.3 + +- Android: migrate to mavenCentral + +## 1.0.2 + +- Fix ios bug https://github.com/fluttercommunity/plus_plugins/issues/198 +- Update android https://github.com/fluttercommunity/plus_plugins/issues/62 +- Update Web class naming conflict https://github.com/fluttercommunity/plus_plugins/issues/260 + +## 1.0.1 + +- Improve documentation + +## 1.0.0 + +- Migrated to null safety + +## 0.8.1 + +- Address pub score + +## 0.8.0 + +- Add Windows support (`connectivity_plus_windows`). +- Removed members that were moved to network_info_plus + +## 0.7.2 + +- Deprecated the following members (use network_info_plus instead): + - getWifiBSSID() + - getWifiIP() + - requestLocationServiceAuthorization() + - getLocationServiceAuthorization() + +## 0.7.1 + +- Bump linux version. + +## 0.7.0 + +- Add Linux support (`connectivity_plus_linux`). + +## 0.6.0 + +- Fix issue #56: Rename Android and iOS classes and Method Channel to avoid + collision with the original connectivity package. + +## 0.5.0 + +- Transfer to plus-plugins monorepo + +## 0.4.9+2 + +- Update package:e2e to use package:integration_test + +## 0.4.9+1 + +- Update package:e2e reference to use the local version in the flutter/plugins + repository. + +## 0.4.9 + +- Add support for `web` (by endorsing `connectivity_for_web` 0.3.0) + +## 0.4.8+6 + +- Update lower bound of dart dependency to 2.1.0. + +## 0.4.8+5 + +- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). + +## 0.4.8+4 + +- Bump the minimum Flutter version to 1.12.13+hotfix.5. +- Clean up various Android workarounds no longer needed after framework v1.12. +- Complete v2 embedding support. +- Fix CocoaPods podspec lint warnings. + +## 0.4.8+3 + +- Replace deprecated `getFlutterEngine` call on Android. + +## 0.4.8+2 + +- Remove hard coded ios workspace setting of the example app. + +## 0.4.8+1 + +- Make the pedantic dev_dependency explicit. + +## 0.4.8 + +- Adds macOS as an endorsed platform. + +## 0.4.7 + +- Migrate the plugin to use the ConnectivityPlatform.instance defined in the connectivity_plus_platform_interface package. + +## 0.4.6+2 + +- Migrate deprecated BinaryMessages to ServicesBinding.instance.defaultBinaryMessenger. +- Bump Flutter SDK to 1.12.13+hotfix.5 or greater (current stable). + +## 0.4.6+1 + +- Remove the deprecated `author:` field from pubspec.yaml +- Migrate the plugin to the pubspec platforms manifest. +- Require Flutter SDK 1.10.0 or greater. + +## 0.4.6 + +- Add macOS support. + +## 0.4.5+8 + +- Update documentation to explain when connectivity updates are received on Android. + +## 0.4.5+7 + +- Fix unawaited futures in the example app and tests. + +## 0.4.5+6 + +- Fix singleton Reachability problem on iOS. + +## 0.4.5+5 + +- Add an analyzer check for the public documentation. + +## 0.4.5+4 + +- Stability and Maintainability: update documentations. + +## 0.4.5+3 + +- Remove AndroidX warnings. + +## 0.4.5+2 + +- Include lifecycle dependency as a compileOnly one on Android to resolve + potential version conflicts with other transitive libraries. + +## 0.4.5+1 + +- Android: Use android.arch.lifecycle instead of androidx.lifecycle:lifecycle in `build.gradle` to support apps that has not been migrated to AndroidX. + +## 0.4.5 + +- Support the v2 Android embedder. + +## 0.4.4+1 + +- Update and migrate iOS example project. +- Define clang module for iOS. + +## 0.4.4 + +- Add `requestLocationServiceAuthorization` to request location authorization on iOS. +- Add `getLocationServiceAuthorization` to get location authorization status on iOS. +- Update README: add more information on iOS 13 updates with CNCopyCurrentNetworkInfo. + +## 0.4.3+7 + +- Update README with the updated information about CNCopyCurrentNetworkInfo on iOS 13. + +## 0.4.3+6 + +- [Android] Fix the invalid suppression check (it should be "deprecation" not "deprecated"). + +## 0.4.3+5 + +- [Android] Added API 29 support for `check()`. +- [Android] Suppress warnings for using deprecated APIs. + +## 0.4.3+4 + +- [Android] Updated logic to retrieve network info. + +## 0.4.3+3 + +- Support for TYPE_MOBILE_HIPRI on Android. + +## 0.4.3+2 + +- Add missing template type parameter to `invokeMethod` calls. + +## 0.4.3+1 + +- Fixes lint error by using `getApplicationContext()` when accessing the Wifi Service. + +## 0.4.3 + +- Add getWifiBSSID to obtain current wifi network's BSSID. + +## 0.4.2+2 + +- Add integration test. + +## 0.4.2+1 + +- Bump the minimum Flutter version to 1.2.0. +- Add template type parameter to `invokeMethod` calls. + +## 0.4.2 + +- Adding getWifiIP() to obtain current wifi network's IP. + +## 0.4.1 + +- Add unit tests. + +## 0.4.0+2 + +- Log a more detailed warning at build time about the previous AndroidX + migration. + +## 0.4.0+1 + +- Updated `Connectivity` to a singleton. + +## 0.4.0 + +- **Breaking change**. Migrate from the deprecated original Android Support + Library to AndroidX. This shouldn't result in any functional changes, but it + requires any Android apps using this plugin to [also + migrate](https://developer.android.com/jetpack/androidx/migrate) if they're + using the original support library. + +## 0.3.2 + +- Adding getWifiName() to obtain current wifi network's SSID. + +## 0.3.1 + +- Updated Gradle tooling to match Android Studio 3.1.2. + +## 0.3.0 + +- **Breaking change**. Set SDK constraints to match the Flutter beta release. + +## 0.2.1 + +- Fixed warnings from the Dart 2.0 analyzer. +- Simplified and upgraded Android project template to Android SDK 27. +- Updated package description. + +## 0.2.0 + +- **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin + 3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in + order to use this version of the plugin. Instructions can be found + [here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1). + +## 0.1.1 + +- Add FLT prefix to iOS types. + +## 0.1.0 + +- Breaking API change: Have a Connectivity class instead of a top level function +- Introduce ability to listen for network state changes + +## 0.0.1 + +- Initial release diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/LICENSE new file mode 100755 index 00000000..7b995420 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/LICENSE @@ -0,0 +1,27 @@ +Copyright 2017 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/README.md new file mode 100755 index 00000000..8eb6ece0 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/README.md @@ -0,0 +1,139 @@ +# connectivity_plus + +[![pub package](https://img.shields.io/pub/v/connectivity_plus.svg)](https://pub.dev/packages/connectivity_plus) +[![pub points](https://img.shields.io/pub/points/connectivity_plus?color=2E8B57&label=pub%20points)](https://pub.dev/packages/connectivity_plus/score) +[![connectivity_plus](https://github.com/fluttercommunity/plus_plugins/actions/workflows/connectivity_plus.yaml/badge.svg)](https://github.com/fluttercommunity/plus_plugins/actions/workflows/connectivity_plus.yaml) + +[](https://flutter.dev/docs/development/packages-and-plugins/favorites) + +This plugin allows Flutter apps to discover network connectivity types that can be used. + +> **Note** +> +> You should not rely on the current connectivity status to decide whether you can reliably make a network request. Always guard your app code against timeouts and errors that might come from the network layer. +> Connection type availability does not guarantee that there is an Internet access. For example, the plugin might return Wi-Fi connection type, but it might be a connection with no Internet access due to network requirements (like on hotel Wi-Fi networks where user often needs to go through a captive portal to authorize first). +> + +## Platform Support + +| Android | iOS | MacOS | Web | Linux | Windows | +| :-----: | :-: | :---: | :-: | :---: | :-----: | +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | + +## Requirements + +- Flutter >=3.7.0 +- Dart >=3.2.0 <4.0.0 +- iOS >=12.0 +- MacOS >=10.14 +- Android `compileSDK` 34 +- Java 17 +- Android Gradle Plugin >=8.3.0 +- Gradle wrapper >=8.4 + +## Usage + +Sample usage to check currently available connection types: + +```dart +import 'package:connectivity_plus/connectivity_plus.dart'; + +final List connectivityResult = await (Connectivity().checkConnectivity()); + +// This condition is for demo purposes only to explain every connection type. +// Use conditions which work for your requirements. +if (connectivityResult.contains(ConnectivityResult.mobile)) { + // Mobile network available. +} else if (connectivityResult.contains(ConnectivityResult.wifi)) { + // Wi-fi is available. + // Note for Android: + // When both mobile and Wi-Fi are turned on system will return Wi-Fi only as active network type +} else if (connectivityResult.contains(ConnectivityResult.ethernet)) { + // Ethernet connection available. +} else if (connectivityResult.contains(ConnectivityResult.vpn)) { + // Vpn connection active. + // Note for iOS and macOS: + // There is no separate network interface type for [vpn]. + // It returns [other] on any device (also simulator) +} else if (connectivityResult.contains(ConnectivityResult.bluetooth)) { + // Bluetooth connection available. +} else if (connectivityResult.contains(ConnectivityResult.other)) { + // Connected to a network which is not in the above mentioned networks. +} else if (connectivityResult.contains(ConnectivityResult.none)) { + // No available network types +} +``` + +You can also listen for active connectivity types changes by subscribing to the stream +exposed by the plugin. + +This method should ensure emitting only distinct values. + +```dart +import 'package:connectivity_plus/connectivity_plus.dart'; + +@override +initState() { + super.initState(); + + StreamSubscription> subscription = Connectivity().onConnectivityChanged.listen((List result) { + // Received changes in available connectivity types! + }); +} + +// Be sure to cancel subscription after you are done +@override +dispose() { + subscription.cancel(); + super.dispose(); +} +``` + +## Platform Support + +The following table shows which `ConnectivityResult` values are supported per platform. + +| | Android | iOS | Web | MacOS | Windows | Linux | +|-----------|:-------:|:---:|:---:|:-----:|:-------:|:-----:| +| wifi | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| bluetooth | :white_check_mark: | | | | | :white_check_mark: | +| ethernet | :white_check_mark: | :white_check_mark: | | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| mobile | :white_check_mark: | :white_check_mark: | | :white_check_mark: | | | +| vpn | :white_check_mark: | | | | :white_check_mark: | :white_check_mark: | +| other | :white_check_mark: | :white_check_mark: | | :white_check_mark: | :white_check_mark: | :white_check_mark: | + +_`none` is supported on all platforms by default._ + +### Android + +Connectivity changes are no longer communicated to Android apps in the background starting with Android O (8.0). You should always check for connectivity status when your app is resumed. The broadcast is only useful when your application is in the foreground. + +### iOS & MacOS + +On iOS simulators, the connectivity types stream might not update when Wi-Fi status changes. This is a known issue. + +Starting with iOS 12 and MacOS 10.14, the implementation uses `NWPathMonitor` to obtain the enabled connectivity types. We noticed that this observer can give multiple or unreliable results. For example, reporting connectivity "none" followed by connectivity "wifi" right after reconnecting. + +We recommend to use the `onConnectivityChanged` with this limitation in mind, as the method doesn't filter events, nor it ensures distinct values. + +### Web + +In order to retrieve information about the quality/speed of a browser's connection, the web implementation of the `connectivity` plugin uses the browser's [**NetworkInformation** Web API](https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation), which as of this writing (June 2020) is still "experimental", and not available in all browsers: + +![Data on support for the netinfo feature across the major browsers from caniuse.com](https://caniuse.bitsofco.de/image/netinfo.png) + +On desktop browsers, this API only returns a very broad set of connectivity statuses (One of `'slow-2g', '2g', '3g', or '4g'`), and may _not_ provide a Stream of changes. Firefox still hasn't enabled this feature by default. + +**Fallback to `navigator.onLine`** + +For those browsers where the NetworkInformation Web API is not available, the plugin falls back to the [**NavigatorOnLine** Web API](https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine), which is more broadly supported: + +![Data on support for the online-status feature across the major browsers from caniuse.com](https://caniuse.bitsofco.de/image/online-status.png) + +The NavigatorOnLine API is [provided by `dart:html`](https://api.dart.dev/stable/2.7.2/dart-html/Navigator/onLine.html), and only supports a boolean connectivity status (either online or offline), with no network speed information. In those cases the plugin will return either `wifi` (when the browser is online) or `none` (when it's not). + +Other than the approximate "downlink" speed, where available, and due to security and privacy concerns, **no Web browser will provide** any specific information about the actual network your users' device is connected to, like **the SSID on a Wi-Fi, or the MAC address of their device.** + +## Learn more + +- [API Documentation](https://pub.dev/documentation/connectivity_plus/latest/connectivity_plus/connectivity_plus-library.html) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/build.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/build.gradle new file mode 100755 index 00000000..6d8c5881 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/build.gradle @@ -0,0 +1,41 @@ +group 'dev.fluttercommunity.plus.connectivity' +version '1.0-SNAPSHOT' + +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.3.1' + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' + +android { + compileSdk 34 + + namespace 'dev.fluttercommunity.plus.connectivity' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + defaultConfig { + minSdk 19 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle.properties new file mode 100755 index 00000000..8bd86f68 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..cae4528d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/settings.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/settings.gradle new file mode 100755 index 00000000..4fbed475 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'connectivity' diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/AndroidManifest.xml new file mode 100755 index 00000000..6435d2cb --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java new file mode 100755 index 00000000..d5e5cbbd --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/Connectivity.java @@ -0,0 +1,121 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.fluttercommunity.plus.connectivity; + +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.os.Build; +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import java.util.ArrayList; +import java.util.List; + +/** Reports connectivity related information such as connectivity type and wifi information. */ +public class Connectivity { + static final String CONNECTIVITY_NONE = "none"; + static final String CONNECTIVITY_WIFI = "wifi"; + static final String CONNECTIVITY_MOBILE = "mobile"; + static final String CONNECTIVITY_ETHERNET = "ethernet"; + static final String CONNECTIVITY_BLUETOOTH = "bluetooth"; + static final String CONNECTIVITY_VPN = "vpn"; + static final String CONNECTIVITY_OTHER = "other"; + private final ConnectivityManager connectivityManager; + + public Connectivity(ConnectivityManager connectivityManager) { + this.connectivityManager = connectivityManager; + } + + List getNetworkTypes() { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Network network = connectivityManager.getActiveNetwork(); + return getCapabilitiesFromNetwork(network); + } else { + // For legacy versions, return a single type as before or adapt similarly if multiple types + // need to be supported + return getNetworkTypesLegacy(); + } + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + List getCapabilitiesFromNetwork(Network network) { + NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network); + return getCapabilitiesList(capabilities); + } + + @NonNull + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + List getCapabilitiesList(NetworkCapabilities capabilities) { + List types = new ArrayList<>(); + if (capabilities == null + || !capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { + types.add(CONNECTIVITY_NONE); + return types; + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) + || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE)) { + types.add(CONNECTIVITY_WIFI); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) { + types.add(CONNECTIVITY_ETHERNET); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { + types.add(CONNECTIVITY_VPN); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + types.add(CONNECTIVITY_MOBILE); + } + if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH)) { + types.add(CONNECTIVITY_BLUETOOTH); + } + if (types.isEmpty() + && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { + types.add(CONNECTIVITY_OTHER); + } + if (types.isEmpty()) { + types.add(CONNECTIVITY_NONE); + } + return types; + } + + @SuppressWarnings("deprecation") + private List getNetworkTypesLegacy() { + // handle type for Android versions less than Android 6 + android.net.NetworkInfo info = connectivityManager.getActiveNetworkInfo(); + List types = new ArrayList<>(); + if (info == null || !info.isConnected()) { + types.add(CONNECTIVITY_NONE); + return types; + } + int type = info.getType(); + switch (type) { + case ConnectivityManager.TYPE_BLUETOOTH: + types.add(CONNECTIVITY_BLUETOOTH); + break; + case ConnectivityManager.TYPE_ETHERNET: + types.add(CONNECTIVITY_ETHERNET); + break; + case ConnectivityManager.TYPE_WIFI: + case ConnectivityManager.TYPE_WIMAX: + types.add(CONNECTIVITY_WIFI); + break; + case ConnectivityManager.TYPE_VPN: + types.add(CONNECTIVITY_VPN); + break; + case ConnectivityManager.TYPE_MOBILE: + case ConnectivityManager.TYPE_MOBILE_DUN: + case ConnectivityManager.TYPE_MOBILE_HIPRI: + types.add(CONNECTIVITY_MOBILE); + break; + default: + types.add(CONNECTIVITY_OTHER); + } + return types; + } + + public ConnectivityManager getConnectivityManager() { + return connectivityManager; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java new file mode 100755 index 00000000..324d3d23 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityBroadcastReceiver.java @@ -0,0 +1,121 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.fluttercommunity.plus.connectivity; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import io.flutter.plugin.common.EventChannel; +import java.util.List; + +/** + * The ConnectivityBroadcastReceiver receives the connectivity updates and send them to the UIThread + * through an {@link EventChannel.EventSink} + * + *

Use {@link + * io.flutter.plugin.common.EventChannel#setStreamHandler(io.flutter.plugin.common.EventChannel.StreamHandler)} + * to set up the receiver. + */ +public class ConnectivityBroadcastReceiver extends BroadcastReceiver + implements EventChannel.StreamHandler { + private final Context context; + private final Connectivity connectivity; + private EventChannel.EventSink events; + private final Handler mainHandler = new Handler(Looper.getMainLooper()); + private ConnectivityManager.NetworkCallback networkCallback; + public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; + + public ConnectivityBroadcastReceiver(Context context, Connectivity connectivity) { + this.context = context; + this.connectivity = connectivity; + } + + @Override + public void onListen(Object arguments, EventChannel.EventSink events) { + this.events = events; + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + networkCallback = + new ConnectivityManager.NetworkCallback() { + @Override + public void onAvailable(Network network) { + // onAvailable is called when the phone switches to a new network + // e.g. the phone was offline and gets wifi connection + // or the phone was on wifi and now switches to mobile. + // The plugin sends the current capability connection to the users. + sendEvent(connectivity.getCapabilitiesFromNetwork(network)); + } + + @Override + public void onCapabilitiesChanged( + Network network, NetworkCapabilities networkCapabilities) { + // This callback is called multiple times after a call to onAvailable + // this also causes multiple callbacks to the Flutter layer. + sendEvent(connectivity.getCapabilitiesList(networkCapabilities)); + } + + @Override + public void onLost(Network network) { + // This callback is called when a capability is lost. + // + // The provided Network object contains information about the + // network capability that has been lost, so we cannot use it. + // + // Instead, post the current network but with a delay long enough + // that we avoid a race condition. + sendCurrentStatusWithDelay(); + } + }; + connectivity.getConnectivityManager().registerDefaultNetworkCallback(networkCallback); + } else { + context.registerReceiver(this, new IntentFilter(CONNECTIVITY_ACTION)); + } + // Need to emit first event with connectivity types without waiting for first change in system + // that might happen much later + sendEvent(connectivity.getNetworkTypes()); + } + + @Override + public void onCancel(Object arguments) { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (networkCallback != null) { + connectivity.getConnectivityManager().unregisterNetworkCallback(networkCallback); + networkCallback = null; + } + } else { + try { + context.unregisterReceiver(this); + } catch (Exception e) { + // listen never called, ignore the error + } + } + } + + @Override + public void onReceive(Context context, Intent intent) { + if (events != null) { + events.success(connectivity.getNetworkTypes()); + } + } + + private void sendEvent(List networkTypes) { + Runnable runnable = () -> events.success(networkTypes); + // Emit events on main thread + mainHandler.post(runnable); + } + + private void sendCurrentStatusWithDelay() { + Runnable runnable = () -> events.success(connectivity.getNetworkTypes()); + // Emit events on main thread + // 500 milliseconds to avoid race conditions + mainHandler.postDelayed(runnable, 500); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java new file mode 100755 index 00000000..e6cfbf1c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityMethodChannelHandler.java @@ -0,0 +1,37 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.fluttercommunity.plus.connectivity; + +import androidx.annotation.NonNull; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; + +/** + * The handler receives {@link MethodCall}s from the UIThread, gets the related information from + * a @{@link Connectivity}, and then send the result back to the UIThread through the {@link + * MethodChannel.Result}. + */ +class ConnectivityMethodChannelHandler implements MethodChannel.MethodCallHandler { + + private final Connectivity connectivity; + + /** + * Construct the ConnectivityMethodChannelHandler with a {@code connectivity}. The {@code + * connectivity} must not be null. + */ + ConnectivityMethodChannelHandler(Connectivity connectivity) { + assert (connectivity != null); + this.connectivity = connectivity; + } + + @Override + public void onMethodCall(MethodCall call, @NonNull MethodChannel.Result result) { + if ("check".equals(call.method)) { + result.success(connectivity.getNetworkTypes()); + } else { + result.notImplemented(); + } + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java new file mode 100755 index 00000000..666cfb83 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/android/src/main/java/dev/fluttercommunity/plus/connectivity/ConnectivityPlugin.java @@ -0,0 +1,56 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.fluttercommunity.plus.connectivity; + +import android.content.Context; +import android.net.ConnectivityManager; +import androidx.annotation.NonNull; +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.EventChannel; +import io.flutter.plugin.common.MethodChannel; + +/** ConnectivityPlugin */ +public class ConnectivityPlugin implements FlutterPlugin { + + private MethodChannel methodChannel; + private EventChannel eventChannel; + private ConnectivityBroadcastReceiver receiver; + + @Override + public void onAttachedToEngine(FlutterPluginBinding binding) { + setupChannels(binding.getBinaryMessenger(), binding.getApplicationContext()); + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + teardownChannels(); + } + + private void setupChannels(BinaryMessenger messenger, Context context) { + methodChannel = new MethodChannel(messenger, "dev.fluttercommunity.plus/connectivity"); + eventChannel = new EventChannel(messenger, "dev.fluttercommunity.plus/connectivity_status"); + ConnectivityManager connectivityManager = + (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + + Connectivity connectivity = new Connectivity(connectivityManager); + + ConnectivityMethodChannelHandler methodChannelHandler = + new ConnectivityMethodChannelHandler(connectivity); + receiver = new ConnectivityBroadcastReceiver(context, connectivity); + + methodChannel.setMethodCallHandler(methodChannelHandler); + eventChannel.setStreamHandler(receiver); + } + + private void teardownChannels() { + methodChannel.setMethodCallHandler(null); + eventChannel.setStreamHandler(null); + receiver.onCancel(null); + methodChannel = null; + eventChannel = null; + receiver = null; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.h new file mode 100755 index 00000000..dc6d193c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.h @@ -0,0 +1,8 @@ +#if TARGET_OS_IOS +#import +#elif TARGET_OS_OSX +#import +#endif + +@interface ConnectivityPlusPlugin : NSObject +@end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.m b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.m new file mode 100755 index 00000000..43af3800 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityPlusPlugin.m @@ -0,0 +1,15 @@ +#import "ConnectivityPlusPlugin.h" +#if __has_include() +#import +#else +// Support project import fallback if the generated compatibility header +// is not copied when this plugin is created as a library. +// https://forums.swift.org/t/swift-static-libraries-dont-copy-generated-objective-c-header/19816 +#import "connectivity_plus-Swift.h" +#endif + +@implementation ConnectivityPlusPlugin ++ (void)registerWithRegistrar:(NSObject *)registrar { + [SwiftConnectivityPlusPlugin registerWithRegistrar:registrar]; +} +@end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityProvider.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityProvider.swift new file mode 100755 index 00000000..ad2cbc1e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/ConnectivityProvider.swift @@ -0,0 +1,21 @@ +import Foundation + +public enum ConnectivityType { + case none + case wiredEthernet + case wifi + case cellular + case other +} + +public protocol ConnectivityProvider: NSObjectProtocol { + typealias ConnectivityUpdateHandler = ([ConnectivityType]) -> Void + + var currentConnectivityTypes: [ConnectivityType] { get } + + var connectivityUpdateHandler: ConnectivityUpdateHandler? { get set } + + func start() + + func stop() +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/PathMonitorConnectivityProvider.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/PathMonitorConnectivityProvider.swift new file mode 100755 index 00000000..d7a8252b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/PathMonitorConnectivityProvider.swift @@ -0,0 +1,69 @@ +import Foundation +import Network + +public class PathMonitorConnectivityProvider: NSObject, ConnectivityProvider { + + // Use .utility, as it is intended for tasks that the user does not track actively. + // See: https://developer.apple.com/documentation/dispatch/dispatchqos + private let queue = DispatchQueue.global(qos: .utility) + + private var pathMonitor: NWPathMonitor? + + private func connectivityFrom(path: NWPath) -> [ConnectivityType] { + var types: [ConnectivityType] = [] + + // Check for connectivity and append to types array as necessary + if path.status == .satisfied { + if path.usesInterfaceType(.wifi) { + types.append(.wifi) + } + if path.usesInterfaceType(.cellular) { + types.append(.cellular) + } + if path.usesInterfaceType(.wiredEthernet) { + types.append(.wiredEthernet) + } + if path.usesInterfaceType(.other) { + types.append(.other) + } + } + + return types.isEmpty ? [.none] : types + } + + public var currentConnectivityTypes: [ConnectivityType] { + let path = ensurePathMonitor().currentPath + return connectivityFrom(path: path) + } + + public var connectivityUpdateHandler: ConnectivityUpdateHandler? + + override init() { + super.init() + _ = ensurePathMonitor() + } + + public func start() { + _ = ensurePathMonitor() + } + + public func stop() { + pathMonitor?.cancel() + pathMonitor = nil + } + + @discardableResult + private func ensurePathMonitor() -> NWPathMonitor { + if (pathMonitor == nil) { + let pathMonitor = NWPathMonitor() + pathMonitor.start(queue: queue) + pathMonitor.pathUpdateHandler = pathUpdateHandler + self.pathMonitor = pathMonitor + } + return self.pathMonitor! + } + + private func pathUpdateHandler(path: NWPath) { + connectivityUpdateHandler?(connectivityFrom(path: path)) + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/SwiftConnectivityPlusPlugin.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/SwiftConnectivityPlusPlugin.swift new file mode 100755 index 00000000..de4ac251 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/Classes/SwiftConnectivityPlusPlugin.swift @@ -0,0 +1,101 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source is governed by a BSD-style license that can +// be found in the LICENSE file. + +#if os(iOS) +import Flutter +#elseif os(macOS) +import Cocoa +import FlutterMacOS +#endif + +public class SwiftConnectivityPlusPlugin: NSObject, FlutterPlugin, FlutterStreamHandler { + private let connectivityProvider: ConnectivityProvider + private var eventSink: FlutterEventSink? + + init(connectivityProvider: ConnectivityProvider) { + self.connectivityProvider = connectivityProvider + super.init() + self.connectivityProvider.connectivityUpdateHandler = connectivityUpdateHandler + } + + public static func register(with registrar: FlutterPluginRegistrar) { + #if os(iOS) + let binaryMessenger = registrar.messenger() + #elseif os(macOS) + let binaryMessenger = registrar.messenger + #endif + + let channel = FlutterMethodChannel( + name: "dev.fluttercommunity.plus/connectivity", + binaryMessenger: binaryMessenger) + + let streamChannel = FlutterEventChannel( + name: "dev.fluttercommunity.plus/connectivity_status", + binaryMessenger: binaryMessenger) + + let connectivityProvider = PathMonitorConnectivityProvider() + let instance = SwiftConnectivityPlusPlugin(connectivityProvider: connectivityProvider) + streamChannel.setStreamHandler(instance) + + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + eventSink = nil + connectivityProvider.stop() + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "check": + result(statusFrom(connectivityTypes: connectivityProvider.currentConnectivityTypes)) + default: + result(FlutterMethodNotImplemented) + } + } + + private func statusFrom(connectivityType: ConnectivityType) -> String { + switch connectivityType { + case .wifi: + return "wifi" + case .cellular: + return "mobile" + case .wiredEthernet: + return "ethernet" + case .other: + return "other" + case .none: + return "none" + } + } + + private func statusFrom(connectivityTypes: [ConnectivityType]) -> [String] { + return connectivityTypes.map { + self.statusFrom(connectivityType: $0) + } + } + + public func onListen( + withArguments _: Any?, + eventSink events: @escaping FlutterEventSink + ) -> FlutterError? { + eventSink = events + connectivityProvider.start() + // Update this to handle a list + connectivityUpdateHandler(connectivityTypes: connectivityProvider.currentConnectivityTypes) + return nil + } + + private func connectivityUpdateHandler(connectivityTypes: [ConnectivityType]) { + DispatchQueue.main.async { + self.eventSink?(self.statusFrom(connectivityTypes: connectivityTypes)) + } + } + + public func onCancel(withArguments _: Any?) -> FlutterError? { + connectivityProvider.stop() + eventSink = nil + return nil + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/PrivacyInfo.xcprivacy b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/PrivacyInfo.xcprivacy new file mode 100755 index 00000000..a34b7e2e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/connectivity_plus.podspec b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/connectivity_plus.podspec new file mode 100755 index 00000000..faa34ac9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/darwin/connectivity_plus.podspec @@ -0,0 +1,30 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'connectivity_plus' + s.version = '0.0.1' + s.summary = 'Flutter Connectivity' + s.description = <<-DESC +This plugin allows Flutter apps to discover network connectivity and configure themselves accordingly. +Downloaded by pub (not CocoaPods). + DESC + s.homepage = 'https://plus.fluttercommunity.dev/' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Community Team' => 'authors@fluttercommunity.dev' } + s.source = { :http => 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/connectivity_plus' } + s.documentation_url = 'https://pub.dev/packages/connectivity_plus' + s.source_files = [ + 'Classes/**/*' + ] + s.public_header_files = [ + 'Classes/**/*.h' + ] + s.ios.dependency 'Flutter' + s.osx.dependency 'FlutterMacOS' + s.ios.deployment_target = '12.0' + s.osx.deployment_target = '10.14' + s.swift_version = '5.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.ios.resource_bundles = {'connectivity_plus_privacy' => ['PrivacyInfo.xcprivacy']} +end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/README.md new file mode 100755 index 00000000..a1356260 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/README.md @@ -0,0 +1,16 @@ +# example + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/analysis_options.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/analysis_options.yaml new file mode 100755 index 00000000..61b6c4de --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +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` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/build.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/build.gradle new file mode 100755 index 00000000..6485aa45 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/build.gradle @@ -0,0 +1,67 @@ +plugins { + id "com.android.application" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + compileSdk 34 + + namespace 'io.flutter.plugins.connectivityexample' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + applicationId "io.flutter.plugins.connectivityexample" + minSdk 21 + targetSdk 34 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test:runner:1.6.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1' +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/AndroidManifest.xml new file mode 100755 index 00000000..b55db54c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java new file mode 100755 index 00000000..0f0dcf25 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/java/io/flutter/plugins/connectivityexample/FlutterActivityTest.java @@ -0,0 +1,17 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.connectivityexample; + +import androidx.test.rule.ActivityTestRule; +import dev.flutter.plugins.integration_test.FlutterTestRunner; +import io.flutter.embedding.android.FlutterActivity; +import org.junit.Rule; +import org.junit.runner.RunWith; + +@RunWith(FlutterTestRunner.class) +public class FlutterActivityTest { + @Rule + public ActivityTestRule rule = new ActivityTestRule<>(FlutterActivity.class); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100755 index 00000000..db77bb4b Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100755 index 00000000..17987b79 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100755 index 00000000..09d43914 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100755 index 00000000..d5f1c8d3 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100755 index 00000000..4d6372ee Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/build.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/build.gradle new file mode 100755 index 00000000..bc157bd1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle.properties new file mode 100755 index 00000000..94adc3a3 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..032437da --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Oct 05 14:43:11 CEST 2021 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/settings.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/settings.gradle new file mode 100755 index 00000000..5fad357a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/android/settings.gradle @@ -0,0 +1,24 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.3.1" apply false +} + +include ":app" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/integration_test/connectivity_plus_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/integration_test/connectivity_plus_test.dart new file mode 100755 index 00000000..fe8cd72f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/integration_test/connectivity_plus_test.dart @@ -0,0 +1,57 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'dart:io'; + +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late Connectivity connectivity; + + group('Connectivity test driver', () { + setUpAll(() async { + connectivity = Connectivity(); + }); + + testWidgets('test connectivity result', (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + expect(result, isNotNull); + }); + + testWidgets('connectivity on Android newer than 5 (API 21) should be wifi', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + + expect(result, [ConnectivityResult.wifi]); + }, + skip: !Platform.isAndroid || + Platform.operatingSystemVersion.contains('5.0.2')); + + testWidgets('connectivity on Android 5 (API 21) should be mobile', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + + expect(result, [ConnectivityResult.mobile]); + }, + skip: !Platform.isAndroid || + !Platform.operatingSystemVersion.contains('5.0.2')); + + testWidgets('connectivity on MacOS should be ethernet', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + + expect(result, [ConnectivityResult.ethernet]); + }, skip: !Platform.isMacOS); + + testWidgets('connectivity on Linux should be none', + (WidgetTester tester) async { + final result = await connectivity.checkConnectivity(); + + expect(result, [ConnectivityResult.other]); + }, skip: !Platform.isLinux); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/AppFrameworkInfo.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100755 index 00000000..7c569640 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Debug.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Debug.xcconfig new file mode 100755 index 00000000..ec97fc6f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Release.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Release.xcconfig new file mode 100755 index 00000000..c4855bfe --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.pbxproj b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..e65736f1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,723 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + B694D755AB7FF7CFD2929C58 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1500449A12D050424A57867A /* Pods_Runner.framework */; }; + F4A8BC5E970EB9B53999ED02 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A8A7721673D9FFDF143C320 /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 1500449A12D050424A57867A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 257D002264E2484E15211C1B /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4190CA09B8971D8AA0EC8FB9 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 5A8A7721673D9FFDF143C320 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + AA3CF93A0B4C03146682AA3A /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + B32C00FEDA2DE2C44D23000B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + CC3B43C8CED1D022483DD294 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + F95E3B38B7E77717BBBD1F33 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1DAEBA9DF8F9603938D62C8C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F4A8BC5E970EB9B53999ED02 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B694D755AB7FF7CFD2929C58 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 4D0D1BE63803AD280C576750 /* Pods */ = { + isa = PBXGroup; + children = ( + 4190CA09B8971D8AA0EC8FB9 /* Pods-Runner.debug.xcconfig */, + 257D002264E2484E15211C1B /* Pods-Runner.release.xcconfig */, + B32C00FEDA2DE2C44D23000B /* Pods-Runner.profile.xcconfig */, + F95E3B38B7E77717BBBD1F33 /* Pods-RunnerTests.debug.xcconfig */, + CC3B43C8CED1D022483DD294 /* Pods-RunnerTests.release.xcconfig */, + AA3CF93A0B4C03146682AA3A /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + 4D0D1BE63803AD280C576750 /* Pods */, + F017D9A85219F51EE7853CBE /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + F017D9A85219F51EE7853CBE /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1500449A12D050424A57867A /* Pods_Runner.framework */, + 5A8A7721673D9FFDF143C320 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 578B235B4B01D5488E7B29F4 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 1DAEBA9DF8F9603938D62C8C /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + F3922377736DD5E91A9CE1B1 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + CAF18DED242B2DB037C2D3CE /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 578B235B4B01D5488E7B29F4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + CAF18DED242B2DB037C2D3CE /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F3922377736DD5E91A9CE1B1 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F95E3B38B7E77717BBBD1F33 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CC3B43C8CED1D022483DD294 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = AA3CF93A0B4C03146682AA3A /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..919434a6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..8e3ca5df --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/AppDelegate.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/AppDelegate.swift new file mode 100755 index 00000000..70693e4a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..d36b1fab --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100755 index 00000000..dc9ada47 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100755 index 00000000..7353c41e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100755 index 00000000..6ed2d933 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100755 index 00000000..4cd7b009 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100755 index 00000000..fe730945 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100755 index 00000000..321773cd Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100755 index 00000000..502f463a Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100755 index 00000000..e9f5fea2 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100755 index 00000000..84ac32ae Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100755 index 00000000..8953cba0 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100755 index 00000000..0467bf12 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100755 index 00000000..0bedcf2f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100755 index 00000000..89c2725b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 00000000..f2e259c7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/Main.storyboard b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100755 index 00000000..f3c28516 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Info.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Info.plist new file mode 100755 index 00000000..5069379d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Connectivity Plus Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + connectivity_plus_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Runner-Bridging-Header.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Runner-Bridging-Header.h new file mode 100755 index 00000000..308a2a56 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/RunnerTests/RunnerTests.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..86a7c3b1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/lib/main.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/lib/main.dart new file mode 100755 index 00000000..29927da5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/lib/main.dart @@ -0,0 +1,125 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'dart:developer' as developer; + +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + useMaterial3: true, + colorSchemeSeed: const Color(0x9f4376f8), + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({Key? key, required this.title}) : super(key: key); + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + List _connectionStatus = [ConnectivityResult.none]; + final Connectivity _connectivity = Connectivity(); + late StreamSubscription> _connectivitySubscription; + + @override + void initState() { + super.initState(); + initConnectivity(); + + _connectivitySubscription = + _connectivity.onConnectivityChanged.listen(_updateConnectionStatus); + } + + @override + void dispose() { + _connectivitySubscription.cancel(); + super.dispose(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future initConnectivity() async { + late List result; + // Platform messages may fail, so we use a try/catch PlatformException. + try { + result = await _connectivity.checkConnectivity(); + } on PlatformException catch (e) { + developer.log('Couldn\'t check connectivity status', error: e); + return; + } + + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) { + return Future.value(null); + } + + return _updateConnectionStatus(result); + } + + Future _updateConnectionStatus(List result) async { + setState(() { + _connectionStatus = result; + }); + // ignore: avoid_print + print('Connectivity changed: $_connectionStatus'); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Connectivity Plus Example'), + elevation: 4, + ), + body: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Spacer(flex: 2), + Text( + 'Active connection types:', + style: Theme.of(context).textTheme.headlineMedium, + ), + const Spacer(), + ListView( + shrinkWrap: true, + children: List.generate( + _connectionStatus.length, + (index) => Center( + child: Text( + _connectionStatus[index].toString(), + style: Theme.of(context).textTheme.headlineSmall, + ), + )), + ), + const Spacer(flex: 2), + ], + ), + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/CMakeLists.txt new file mode 100755 index 00000000..279007eb --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "io.flutter.plugins.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..5b465c7e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/main.cc b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/main.cc new file mode 100755 index 00000000..8bc15615 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/main.cc @@ -0,0 +1,11 @@ +#include "my_application.h" + +int main(int argc, char **argv) { + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); + + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.cc b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.cc new file mode 100755 index 00000000..cef2f771 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.cc @@ -0,0 +1,45 @@ +#include "my_application.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication *application) { + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +static void my_application_class_init(MyApplicationClass *klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; +} + +static void my_application_init(MyApplication *self) {} + +MyApplication *my_application_new() { + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.h new file mode 100755 index 00000000..3258a73c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication *my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Debug.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100755 index 00000000..4b81f9b2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Release.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100755 index 00000000..5caa9d15 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.pbxproj b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..eab0503a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,791 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 516D2749BEC98FB8007BDD39 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5680711160F3554DA073A4A /* Pods_Runner.framework */; }; + A0DE1A8BAD92B1FC97AF3072 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7DE3F356208F8AF32BF63FB /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2DA90B2343051DD978570433 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 32DD3AA8862D40CEC34F4823 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* connectivity_plus_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_device_info.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 818BD3063832BFCCEB86E2DC /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 849CE1B58CE95AE709338025 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + A5680711160F3554DA073A4A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A7DE3F356208F8AF32BF63FB /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BC7DC07E4588932BDF542A1C /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + F074D7F65F9EE14BDF366DEA /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A0DE1A8BAD92B1FC97AF3072 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 516D2749BEC98FB8007BDD39 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + 7C46BB738D7DFC62A80734E0 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* example_device_info.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + 7C46BB738D7DFC62A80734E0 /* Pods */ = { + isa = PBXGroup; + children = ( + 849CE1B58CE95AE709338025 /* Pods-Runner.debug.xcconfig */, + F074D7F65F9EE14BDF366DEA /* Pods-Runner.release.xcconfig */, + 32DD3AA8862D40CEC34F4823 /* Pods-Runner.profile.xcconfig */, + BC7DC07E4588932BDF542A1C /* Pods-RunnerTests.debug.xcconfig */, + 2DA90B2343051DD978570433 /* Pods-RunnerTests.release.xcconfig */, + 818BD3063832BFCCEB86E2DC /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A5680711160F3554DA073A4A /* Pods_Runner.framework */, + A7DE3F356208F8AF32BF63FB /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + E6B78D17FAAB2457BAC2FC37 /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 290ED1BDB70728341B0EE329 /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 9130A189025A19331F12A8D2 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* example_device_info.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 290ED1BDB70728341B0EE329 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 9130A189025A19331F12A8D2 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E6B78D17FAAB2457BAC2FC37 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = BC7DC07E4588932BDF542A1C /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/connectivity_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/connectivity_plus_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2DA90B2343051DD978570433 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/connectivity_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/connectivity_plus_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 818BD3063832BFCCEB86E2DC /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlusExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/connectivity_plus_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/connectivity_plus_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..fa25347e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/AppDelegate.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/AppDelegate.swift new file mode 100755 index 00000000..d53ef643 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..a2ec33f1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "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" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100755 index 00000000..82b6f9d9 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100755 index 00000000..13b35eba Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100755 index 00000000..0a3f5fa4 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100755 index 00000000..bdb57226 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100755 index 00000000..f083318e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100755 index 00000000..326c0e72 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100755 index 00000000..2f1632cf Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Base.lproj/MainMenu.xib b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100755 index 00000000..80e867a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/AppInfo.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100755 index 00000000..516d9adf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = connectivity_plus_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.connectivityPlus.example + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 io.flutter.plugins. All rights reserved. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Debug.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Debug.xcconfig new file mode 100755 index 00000000..36b0fd94 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Release.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Release.xcconfig new file mode 100755 index 00000000..dff4f495 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Warnings.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100755 index 00000000..42bcbf47 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/DebugProfile.entitlements b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/DebugProfile.entitlements new file mode 100755 index 00000000..dddb8a30 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Info.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Info.plist new file mode 100755 index 00000000..4789daa6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/MainFlutterWindow.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/MainFlutterWindow.swift new file mode 100755 index 00000000..3cc05eb2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Release.entitlements b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Release.entitlements new file mode 100755 index 00000000..852fa1a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/RunnerTests/RunnerTests.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..5418c9f5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/pubspec.yaml new file mode 100755 index 00000000..64fc0b64 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/pubspec.yaml @@ -0,0 +1,23 @@ +name: connectivity_plus_example +description: Demonstrates how to use the connectivity_plus plugin. + +environment: + sdk: '>=2.12.0 <4.0.0' + +dependencies: + flutter: + sdk: flutter + connectivity_plus: ^6.0.5 + +dev_dependencies: + flutter_driver: + sdk: flutter + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + test: ^1.16.4 + flutter_lints: ^4.0.0 + +flutter: + uses-material-design: true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/favicon.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/favicon.png new file mode 100755 index 00000000..8aaa46ac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/favicon.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-192.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-192.png new file mode 100755 index 00000000..b749bfef Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-192.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-512.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-512.png new file mode 100755 index 00000000..88cfd48d Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-512.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-192.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-192.png new file mode 100755 index 00000000..eb9b4d76 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-192.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-512.png b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-512.png new file mode 100755 index 00000000..d69c5669 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/icons/Icon-maskable-512.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/index.html b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/index.html new file mode 100755 index 00000000..9b7a438f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/index.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + example + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/manifest.json b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/manifest.json new file mode 100755 index 00000000..8c012917 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/CMakeLists.txt new file mode 100755 index 00000000..abf90408 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.15) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..b02c5485 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..977e38b5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/Runner.rc b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/Runner.rc new file mode 100755 index 00000000..f414c2d8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "io.flutter.plugins" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 io.flutter.plugins. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..0f0105d9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.cpp @@ -0,0 +1,64 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opporutunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..69234d4f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/flutter_window.h @@ -0,0 +1,39 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "run_loop.h" +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { +public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + virtual ~FlutterWindow(); + +protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + +private: + // The run loop driving events for this window. + RunLoop *run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/main.cpp new file mode 100755 index 00000000..09895686 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/main.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resource.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resources/app_icon.ico b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/resources/app_icon.ico differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.cpp new file mode 100755 index 00000000..31b89f62 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.cpp @@ -0,0 +1,66 @@ +#include "run_loop.h" + +#include + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto instance : flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.h new file mode 100755 index 00000000..7fe1aacc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/run_loop.h @@ -0,0 +1,38 @@ +#ifndef RUNNER_RUN_LOOP_H_ +#define RUNNER_RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { +public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const &) = delete; + RunLoop &operator=(RunLoop const &) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + +private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUNNER_RUN_LOOP_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/runner.exe.manifest b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.cpp new file mode 100755 index 00000000..7758aabf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.cpp @@ -0,0 +1,63 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t *utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.h new file mode 100755 index 00000000..ff43ce2c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t *utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..90ff01e5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.cpp @@ -0,0 +1,237 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { +public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + +private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar *instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; + +const wchar_t *WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size) { + Destroy(); + + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window *that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.h new file mode 100755 index 00000000..7b518125 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/example/windows/runner/win32_window.h @@ -0,0 +1,95 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { +public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/connectivity_plus.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/connectivity_plus.dart new file mode 100755 index 00000000..cef5ddee --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/connectivity_plus.dart @@ -0,0 +1,66 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:collection/collection.dart'; + +// Export enums from the platform_interface so plugin users can use them directly. +export 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart' + show ConnectivityResult; + +export 'src/connectivity_plus_linux.dart' + if (dart.library.js_interop) 'src/connectivity_plus_web.dart'; + +/// Discover network connectivity configurations: Distinguish between WI-FI and cellular, check WI-FI status and more. +class Connectivity { + /// Constructs a singleton instance of [Connectivity]. + /// + /// [Connectivity] is designed to work as a singleton. + // When a second instance is created, the first instance will not be able to listen to the + // EventChannel because it is overridden. Forcing the class to be a singleton class can prevent + // misuse of creating a second instance from a programmer. + factory Connectivity() { + _singleton ??= Connectivity._(); + return _singleton!; + } + + Connectivity._(); + + static Connectivity? _singleton; + + static ConnectivityPlatform get _platform { + return ConnectivityPlatform.instance; + } + + /// Exposes connectivity update events from the platform. + /// + /// On iOS, the connectivity status might not update when WiFi + /// status changes, this is a known issue that only affects simulators. + /// For details see https://github.com/fluttercommunity/plus_plugins/issues/479. + /// + /// The emitted list is never empty. In case of no connectivity, the list contains + /// a single element of [ConnectivityResult.none]. Note also that this is the only + /// case where [ConnectivityResult.none] is present. + /// + /// This method applies [Stream.distinct] over the received events to ensure + /// only emiting when connectivity changes. + Stream> get onConnectivityChanged { + return _platform.onConnectivityChanged.distinct((a, b) => a.equals(b)); + } + + /// Checks the connection status of the device. + /// + /// Do not use the result of this function to decide whether you can reliably + /// make a network request, it only gives you the radio status. Instead, listen + /// for connectivity changes via [onConnectivityChanged] stream. + /// + /// The returned list is never empty. In case of no connectivity, the list contains + /// a single element of [ConnectivityResult.none]. Note also that this is the only + /// case where [ConnectivityResult.none] is present. + Future> checkConnectivity() { + return _platform.checkConnectivity(); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_linux.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_linux.dart new file mode 100755 index 00000000..31b562aa --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_linux.dart @@ -0,0 +1,94 @@ +import 'dart:async'; + +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:meta/meta.dart'; +import 'package:nm/nm.dart'; + +// Used internally +// ignore_for_file: public_member_api_docs + +@visibleForTesting +typedef NetworkManagerClientFactory = NetworkManagerClient Function(); + +/// The Linux implementation of ConnectivityPlatform. +class ConnectivityPlusLinuxPlugin extends ConnectivityPlatform { + /// Register this dart class as the platform implementation for linux + static void registerWith() { + ConnectivityPlatform.instance = ConnectivityPlusLinuxPlugin(); + } + + /// Checks the connection status of the device. + @override + Future> checkConnectivity() async { + final client = createClient(); + await client.connect(); + final connectivity = _getConnectivity(client); + await client.close(); + return connectivity; + } + + NetworkManagerClient? _client; + StreamController>? _controller; + + /// Returns a Stream of ConnectivityResults changes. + @override + Stream> get onConnectivityChanged { + _controller ??= StreamController>.broadcast( + onListen: _startListenConnectivity, + onCancel: _stopListenConnectivity, + ); + return _controller!.stream; + } + + List _getConnectivity(NetworkManagerClient client) { + final List results = []; + if (client.connectivity == NetworkManagerConnectivityState.none) { + results.add(ConnectivityResult.none); + } else { + if (client.primaryConnectionType.contains('wireless')) { + results.add(ConnectivityResult.wifi); + } + if (client.primaryConnectionType.contains('ethernet')) { + results.add(ConnectivityResult.ethernet); + } + if (client.primaryConnectionType.contains('vpn')) { + results.add(ConnectivityResult.vpn); + } + if (client.primaryConnectionType.contains('bluetooth')) { + results.add(ConnectivityResult.bluetooth); + } + if (client.primaryConnectionType.contains('mobile')) { + results.add(ConnectivityResult.mobile); + } + // Assuming 'other' is a catch-all for unspecified types + if (results.isEmpty) { + results.add(ConnectivityResult.other); + } + } + return results; + } + + Future _startListenConnectivity() async { + _client ??= createClient(); + await _client!.connect(); + _addConnectivity(_client!); + _client!.propertiesChanged.listen((properties) { + if (properties.contains('Connectivity')) { + _addConnectivity(_client!); + } + }); + } + + void _addConnectivity(NetworkManagerClient client) { + _controller!.add(_getConnectivity(client)); + } + + Future _stopListenConnectivity() async { + await _client?.close(); + _client = null; + } + + @visibleForTesting + // ignore: prefer_function_declarations_over_variables + NetworkManagerClientFactory createClient = () => NetworkManagerClient(); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_web.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_web.dart new file mode 100755 index 00000000..d2f35d5d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/connectivity_plus_web.dart @@ -0,0 +1,13 @@ +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +import 'web/dart_html_connectivity_plugin.dart'; + +/// The web implementation of the ConnectivityPlatform of the Connectivity plugin. +class ConnectivityPlusWebPlugin extends ConnectivityPlatform { + /// Factory method that initializes the connectivity plugin platform with an instance + /// of the plugin for the web. + static void registerWith(Registrar registrar) { + ConnectivityPlatform.instance = DartHtmlConnectivityPlugin(); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/dart_html_connectivity_plugin.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/dart_html_connectivity_plugin.dart new file mode 100755 index 00000000..0ad59a6d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/dart_html_connectivity_plugin.dart @@ -0,0 +1,35 @@ +import 'dart:async'; +import 'package:web/web.dart'; + +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; + +import '../connectivity_plus_web.dart'; + +/// The web implementation of the ConnectivityPlatform of the Connectivity plugin. +class DartHtmlConnectivityPlugin extends ConnectivityPlusWebPlugin { + /// Checks the connection status of the device. + @override + Future> checkConnectivity() async { + return (window.navigator.onLine) + ? [ConnectivityResult.wifi] + : [ConnectivityResult.none]; + } + + StreamController>? _connectivityResult; + + /// Returns a Stream of ConnectivityResults changes. + @override + Stream> get onConnectivityChanged { + if (_connectivityResult == null) { + _connectivityResult = + StreamController>.broadcast(); + const EventStreamProvider('online').forTarget(window).listen((_) { + _connectivityResult!.add([ConnectivityResult.wifi]); + }); + const EventStreamProvider('offline').forTarget(window).listen((_) { + _connectivityResult!.add([ConnectivityResult.none]); + }); + } + return _connectivityResult!.stream; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/utils/connectivity_result.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/utils/connectivity_result.dart new file mode 100755 index 00000000..c3250f19 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/lib/src/web/utils/connectivity_result.dart @@ -0,0 +1,58 @@ +import 'dart:html' as html show NetworkInformation; + +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; + +/// Converts an incoming NetworkInformation object into the correct ConnectivityResult. +List networkInformationToConnectivityResult( + html.NetworkInformation info, +) { + if (info.downlink == 0 && info.rtt == 0) { + return [ConnectivityResult.none]; + } + if (info.type != null) { + return _typeToConnectivityResult(info.type!); + } + if (info.effectiveType != null) { + return _effectiveTypeToConnectivityResult(info.effectiveType!); + } + return [ConnectivityResult.none]; +} + +List _effectiveTypeToConnectivityResult( + String effectiveType) { + // Possible values: + /*'2g'|'3g'|'4g'|'slow-2g'*/ + switch (effectiveType) { + case 'slow-2g': + case '2g': + case '3g': + case '4g': + return [ConnectivityResult.mobile]; + default: + return [ConnectivityResult.wifi]; + } +} + +List _typeToConnectivityResult(String type) { + // Possible values: 'bluetooth', 'cellular', 'ethernet', 'mixed', 'none', 'other', 'unknown', 'wifi', 'wimax' + switch (type) { + case 'none': + // Corrected to return a list + return [ConnectivityResult.none]; + case 'bluetooth': + return [ConnectivityResult.bluetooth]; + case 'cellular': + case 'mixed': + case 'other': + case 'unknown': + return [ConnectivityResult.mobile]; + case 'ethernet': + return [ConnectivityResult.ethernet]; + case 'wifi': + case 'wimax': // Assuming 'wimax' should be treated the same as 'wifi' + return [ConnectivityResult.wifi]; + default: + // Assuming default should be 'other' to cover all unspecified cases + return [ConnectivityResult.other]; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/pubspec.yaml new file mode 100755 index 00000000..66956fff --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/pubspec.yaml @@ -0,0 +1,57 @@ +name: connectivity_plus +description: Flutter plugin for discovering the state of the network (WiFi & mobile/cellular) connectivity on Android and iOS. +version: 6.0.5 +homepage: https://github.com/fluttercommunity/plus_plugins +repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/connectivity_plus/connectivity_plus +issue_tracker: https://github.com/fluttercommunity/plus_plugins/labels/connectivity_plus +topics: + - connectivity + - utils + +environment: + sdk: ">=3.2.0 <4.0.0" + # Flutter versions prior to 3.7 did not support the + # sharedDarwinSource option. + flutter: ">=3.7.0" + +flutter: + plugin: + platforms: + android: + package: dev.fluttercommunity.plus.connectivity + pluginClass: ConnectivityPlugin + ios: + pluginClass: ConnectivityPlusPlugin + sharedDarwinSource: true + + linux: + dartPluginClass: ConnectivityPlusLinuxPlugin + macos: + pluginClass: ConnectivityPlusPlugin + sharedDarwinSource: true + web: + pluginClass: ConnectivityPlusWebPlugin + fileName: src/connectivity_plus_web.dart + windows: + pluginClass: ConnectivityPlusWindowsPlugin + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + connectivity_plus_platform_interface: ^2.0.1 + web: ">=0.5.0 <2.0.0" + meta: ^1.8.0 + nm: ^0.5.0 + collection: ^1.18.0 + +dev_dependencies: + flutter_test: + sdk: flutter + build_runner: ^2.3.3 + dbus: ^0.7.8 + flutter_lints: ^4.0.0 + mockito: ^5.4.0 + plugin_platform_interface: ^2.1.5 + test: ^1.22.0 diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.dart new file mode 100755 index 00000000..b7ecf03c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.dart @@ -0,0 +1,125 @@ +import 'package:connectivity_plus/src/connectivity_plus_linux.dart'; +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:nm/nm.dart'; + +import 'connectivity_plus_linux_test.mocks.dart'; + +@GenerateMocks([NetworkManagerClient]) +void main() { + test('registered instance', () { + ConnectivityPlusLinuxPlugin.registerWith(); + expect(ConnectivityPlatform.instance, isA()); + }); + + test('bluetooth', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('bluetooth'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.bluetooth])), + ); + }); + + test('ethernet', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('ethernet'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.ethernet])), + ); + }); + + test('wireless', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('wireless'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.wifi])), + ); + }); + + test('vpn', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('vpn'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.vpn])), + ); + }); + + test('wireless+vpn', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('wireless,vpn'); + return client; + }; + expect( + linux.checkConnectivity(), + completion(equals([ConnectivityResult.wifi, ConnectivityResult.vpn])), + ); + }); + + test('no connectivity', () async { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.none); + return client; + }; + expect(linux.checkConnectivity(), + completion(equals([ConnectivityResult.none]))); + }); + + test('connectivity changes', () { + final linux = ConnectivityPlusLinuxPlugin(); + linux.createClient = () { + final client = MockNetworkManagerClient(); + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.full); + when(client.primaryConnectionType).thenReturn('wireless'); + when(client.propertiesChanged).thenAnswer((_) { + when(client.connectivity) + .thenReturn(NetworkManagerConnectivityState.none); + return Stream.value(['Connectivity']); + }); + return client; + }; + expect( + linux.onConnectivityChanged, + emitsInOrder([ + [ConnectivityResult.wifi], + [ConnectivityResult.none] + ])); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart new file mode 100755 index 00000000..9e1ffbcf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_plus_linux_test.mocks.dart @@ -0,0 +1,205 @@ +// Mocks generated by Mockito 5.2.0 from annotations +// in connectivity_plus_linux/test/connectivity_plus_linux_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i3; + +import 'package:dbus/dbus.dart' as _i4; +import 'package:mockito/mockito.dart' as _i1; +import 'package:nm/src/network_manager_client.dart' as _i2; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types + +class _FakeNetworkManagerSettings_0 extends _i1.Fake + implements _i2.NetworkManagerSettings {} + +class _FakeNetworkManagerDnsManager_1 extends _i1.Fake + implements _i2.NetworkManagerDnsManager {} + +class _FakeNetworkManagerActiveConnection_2 extends _i1.Fake + implements _i2.NetworkManagerActiveConnection {} + +/// A class which mocks [NetworkManagerClient]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockNetworkManagerClient extends _i1.Mock + implements _i2.NetworkManagerClient { + MockNetworkManagerClient() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Stream<_i2.NetworkManagerDevice> get deviceAdded => + (super.noSuchMethod(Invocation.getter(#deviceAdded), + returnValue: Stream<_i2.NetworkManagerDevice>.empty()) + as _i3.Stream<_i2.NetworkManagerDevice>); + @override + _i3.Stream<_i2.NetworkManagerDevice> get deviceRemoved => + (super.noSuchMethod(Invocation.getter(#deviceRemoved), + returnValue: Stream<_i2.NetworkManagerDevice>.empty()) + as _i3.Stream<_i2.NetworkManagerDevice>); + @override + _i3.Stream<_i2.NetworkManagerActiveConnection> get activeConnectionAdded => + (super.noSuchMethod(Invocation.getter(#activeConnectionAdded), + returnValue: Stream<_i2.NetworkManagerActiveConnection>.empty()) + as _i3.Stream<_i2.NetworkManagerActiveConnection>); + @override + _i3.Stream<_i2.NetworkManagerActiveConnection> get activeConnectionRemoved => + (super.noSuchMethod(Invocation.getter(#activeConnectionRemoved), + returnValue: Stream<_i2.NetworkManagerActiveConnection>.empty()) + as _i3.Stream<_i2.NetworkManagerActiveConnection>); + @override + _i3.Stream> get propertiesChanged => (super.noSuchMethod( + Invocation.getter(#propertiesChanged), + returnValue: Stream>.empty()) as _i3.Stream>); + @override + List<_i2.NetworkManagerDevice> get devices => + (super.noSuchMethod(Invocation.getter(#devices), + returnValue: <_i2.NetworkManagerDevice>[]) + as List<_i2.NetworkManagerDevice>); + @override + List<_i2.NetworkManagerDevice> get allDevices => + (super.noSuchMethod(Invocation.getter(#allDevices), + returnValue: <_i2.NetworkManagerDevice>[]) + as List<_i2.NetworkManagerDevice>); + @override + bool get networkingEnabled => + (super.noSuchMethod(Invocation.getter(#networkingEnabled), + returnValue: false) as bool); + @override + bool get wirelessEnabled => (super + .noSuchMethod(Invocation.getter(#wirelessEnabled), returnValue: false) + as bool); + @override + bool get wirelessHardwareEnabled => + (super.noSuchMethod(Invocation.getter(#wirelessHardwareEnabled), + returnValue: false) as bool); + @override + bool get wwanEnabled => + (super.noSuchMethod(Invocation.getter(#wwanEnabled), returnValue: false) + as bool); + @override + bool get wwanHardwareEnabled => + (super.noSuchMethod(Invocation.getter(#wwanHardwareEnabled), + returnValue: false) as bool); + @override + List<_i2.NetworkManagerActiveConnection> get activeConnections => + (super.noSuchMethod(Invocation.getter(#activeConnections), + returnValue: <_i2.NetworkManagerActiveConnection>[]) + as List<_i2.NetworkManagerActiveConnection>); + @override + String get primaryConnectionType => + (super.noSuchMethod(Invocation.getter(#primaryConnectionType), + returnValue: '') as String); + @override + _i2.NetworkManagerMetered get metered => + (super.noSuchMethod(Invocation.getter(#metered), + returnValue: _i2.NetworkManagerMetered.unknown) + as _i2.NetworkManagerMetered); + @override + bool get startup => + (super.noSuchMethod(Invocation.getter(#startup), returnValue: false) + as bool); + @override + String get version => + (super.noSuchMethod(Invocation.getter(#version), returnValue: '') + as String); + @override + _i2.NetworkManagerConnectivityState get connectivity => + (super.noSuchMethod(Invocation.getter(#connectivity), + returnValue: _i2.NetworkManagerConnectivityState.unknown) + as _i2.NetworkManagerConnectivityState); + @override + bool get connectivityCheckAvailable => + (super.noSuchMethod(Invocation.getter(#connectivityCheckAvailable), + returnValue: false) as bool); + @override + bool get connectivityCheckEnabled => + (super.noSuchMethod(Invocation.getter(#connectivityCheckEnabled), + returnValue: false) as bool); + @override + String get connectivityCheckUri => + (super.noSuchMethod(Invocation.getter(#connectivityCheckUri), + returnValue: '') as String); + @override + _i2.NetworkManagerState get state => (super.noSuchMethod( + Invocation.getter(#state), + returnValue: _i2.NetworkManagerState.unknown) as _i2.NetworkManagerState); + @override + _i2.NetworkManagerSettings get settings => + (super.noSuchMethod(Invocation.getter(#settings), + returnValue: _FakeNetworkManagerSettings_0()) + as _i2.NetworkManagerSettings); + @override + _i2.NetworkManagerDnsManager get dnsManager => + (super.noSuchMethod(Invocation.getter(#dnsManager), + returnValue: _FakeNetworkManagerDnsManager_1()) + as _i2.NetworkManagerDnsManager); + @override + _i3.Future connect() => + (super.noSuchMethod(Invocation.method(#connect, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future setWirelessEnabled(bool? value) => + (super.noSuchMethod(Invocation.method(#setWirelessEnabled, [value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future setWwanEnabled(bool? value) => + (super.noSuchMethod(Invocation.method(#setWwanEnabled, [value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future setConnectivityCheckEnabled(bool? value) => (super + .noSuchMethod(Invocation.method(#setConnectivityCheckEnabled, [value]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future<_i2.NetworkManagerActiveConnection> addAndActivateConnection( + {Map>? connection = const {}, + _i2.NetworkManagerDevice? device, + _i2.NetworkManagerAccessPoint? accessPoint}) => + (super.noSuchMethod( + Invocation.method(#addAndActivateConnection, [], { + #connection: connection, + #device: device, + #accessPoint: accessPoint + }), + returnValue: Future<_i2.NetworkManagerActiveConnection>.value( + _FakeNetworkManagerActiveConnection_2())) + as _i3.Future<_i2.NetworkManagerActiveConnection>); + @override + _i3.Future<_i2.NetworkManagerActiveConnection> activateConnection( + {_i2.NetworkManagerDevice? device, + _i2.NetworkManagerSettingsConnection? connection, + _i2.NetworkManagerAccessPoint? accessPoint}) => + (super.noSuchMethod( + Invocation.method(#activateConnection, [], { + #device: device, + #connection: connection, + #accessPoint: accessPoint + }), + returnValue: Future<_i2.NetworkManagerActiveConnection>.value( + _FakeNetworkManagerActiveConnection_2())) + as _i3.Future<_i2.NetworkManagerActiveConnection>); + @override + _i3.Future deactivateConnection( + _i2.NetworkManagerActiveConnection? connection) => + (super.noSuchMethod( + Invocation.method(#deactivateConnection, [connection]), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); + @override + _i3.Future close() => (super.noSuchMethod(Invocation.method(#close, []), + returnValue: Future.value(), + returnValueForMissingStub: Future.value()) as _i3.Future); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_test.dart new file mode 100755 index 00000000..4f177c0f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/test/connectivity_test.dart @@ -0,0 +1,39 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:connectivity_plus/connectivity_plus.dart'; +import 'package:connectivity_plus_platform_interface/connectivity_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; +import 'package:mockito/mockito.dart'; + +const List kCheckConnectivityResult = [ + ConnectivityResult.wifi +]; + +void main() { + group('Connectivity', () { + late Connectivity connectivity; + MockConnectivityPlatform fakePlatform; + setUp(() async { + fakePlatform = MockConnectivityPlatform(); + ConnectivityPlatform.instance = fakePlatform; + connectivity = Connectivity(); + }); + + test('checkConnectivity', () async { + final result = await connectivity.checkConnectivity(); + expect(result, kCheckConnectivityResult); + }); + }); +} + +class MockConnectivityPlatform extends Mock + with MockPlatformInterfaceMixin + implements ConnectivityPlatform { + @override + Future> checkConnectivity() async { + return kCheckConnectivityResult; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/CMakeLists.txt new file mode 100755 index 00000000..ac315ccd --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.15) +set(PROJECT_NAME "connectivity_plus") +project(${PROJECT_NAME} LANGUAGES CXX) + +# This value is used when generating builds using this plugin, so it must +# not be changed +set(PLUGIN_NAME "connectivity_plus_plugin") + +add_library(${PLUGIN_NAME} SHARED + "connectivity_plus_plugin.cpp" + "network_manager.cpp" +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE + flutter + flutter_wrapper_plugin + iphlpapi +) + +# List of absolute paths to libraries that should be bundled with the plugin +set(connectivity_plus_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/connectivity_plus_plugin.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/connectivity_plus_plugin.cpp new file mode 100755 index 00000000..cb6ae1f9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/connectivity_plus_plugin.cpp @@ -0,0 +1,189 @@ +// clang-format off +#include "include/connectivity_plus/network_manager.h" +// clang-format on +#include "include/connectivity_plus/connectivity_plus_windows_plugin.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace { + +typedef flutter::EventChannel FlEventChannel; +typedef flutter::EventSink FlEventSink; +typedef flutter::MethodCall FlMethodCall; +typedef flutter::MethodResult FlMethodResult; +typedef flutter::MethodChannel FlMethodChannel; +typedef flutter::StreamHandler FlStreamHandler; +typedef flutter::StreamHandlerError + FlStreamHandlerError; + +class ConnectivityPlusWindowsPlugin : public flutter::Plugin { +public: + ConnectivityPlusWindowsPlugin(); + virtual ~ConnectivityPlusWindowsPlugin(); + + std::shared_ptr GetManager() const; + + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); + +private: + void HandleMethodCall(const FlMethodCall &method_call, + std::unique_ptr result); + + std::shared_ptr manager; +}; + +class ConnectivityStreamHandler : public FlStreamHandler { +public: + ConnectivityStreamHandler(std::shared_ptr manager); + virtual ~ConnectivityStreamHandler(); + +protected: + void AddConnectivityEvent(); + + std::unique_ptr + OnListenInternal(const flutter::EncodableValue *arguments, + std::unique_ptr &&sink) override; + + std::unique_ptr + OnCancelInternal(const flutter::EncodableValue *arguments) override; + +private: + std::shared_ptr manager; + std::unique_ptr sink; +}; + +ConnectivityPlusWindowsPlugin::ConnectivityPlusWindowsPlugin() { + manager = std::make_shared(); + manager->Init(); +} + +ConnectivityPlusWindowsPlugin::~ConnectivityPlusWindowsPlugin() { + manager->Cleanup(); +} + +std::shared_ptr +ConnectivityPlusWindowsPlugin::GetManager() const { + return manager; +} + +void ConnectivityPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows *registrar) { + auto plugin = std::make_unique(); + + auto methodChannel = + std::make_unique>( + registrar->messenger(), "dev.fluttercommunity.plus/connectivity", + &flutter::StandardMethodCodec::GetInstance()); + + methodChannel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto &call, auto result) { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); + + auto eventChannel = std::make_unique( + registrar->messenger(), "dev.fluttercommunity.plus/connectivity_status", + &flutter::StandardMethodCodec::GetInstance()); + + eventChannel->SetStreamHandler( + std::make_unique(plugin->GetManager())); + + registrar->AddPlugin(std::move(plugin)); +} + +static std::string ConnectivityToString(ConnectivityType connectivityType) { + switch (connectivityType) { + case ConnectivityType::WiFi: + return "wifi"; + case ConnectivityType::Ethernet: + return "ethernet"; + case ConnectivityType::VPN: + return "vpn"; + case ConnectivityType::Other: + return "other"; + case ConnectivityType::None: + default: + return "none"; + } +} + +static flutter::EncodableList +EncodeConnectivityTypes(std::set connectivityTypes) { + flutter::EncodableList encodedList; + + if (connectivityTypes.empty()) { + encodedList.push_back( + flutter::EncodableValue(ConnectivityToString(ConnectivityType::None))); + return encodedList; + } + + for (const auto &type : connectivityTypes) { + std::string connectivityString = ConnectivityToString(type); + encodedList.push_back(flutter::EncodableValue(connectivityString)); + } + + return encodedList; +} + +void ConnectivityPlusWindowsPlugin::HandleMethodCall( + const flutter::MethodCall &method_call, + std::unique_ptr> result) { + if (method_call.method_name().compare("check") == 0) { + result->Success(EncodeConnectivityTypes(manager->GetConnectivityTypes())); + } else { + result->NotImplemented(); + } +} + +ConnectivityStreamHandler::ConnectivityStreamHandler( + std::shared_ptr manager) + : manager(manager) {} + +ConnectivityStreamHandler::~ConnectivityStreamHandler() {} + +void ConnectivityStreamHandler::AddConnectivityEvent() { + sink->Success(EncodeConnectivityTypes(manager->GetConnectivityTypes())); +} + +std::unique_ptr +ConnectivityStreamHandler::OnListenInternal( + const flutter::EncodableValue *arguments, + std::unique_ptr &&events) { + sink = std::move(events); + + auto callback = + std::bind(&ConnectivityStreamHandler::AddConnectivityEvent, this); + + if (!manager->StartListen(callback)) { + return std::make_unique( + std::to_string(manager->GetError()), "NetworkManager::StartListen", + nullptr); + } + + AddConnectivityEvent(); + return nullptr; +} + +std::unique_ptr +ConnectivityStreamHandler::OnCancelInternal( + const flutter::EncodableValue *arguments) { + manager->StopListen(); + sink.reset(); + return nullptr; +} + +} // namespace + +void ConnectivityPlusWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + ConnectivityPlusWindowsPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h new file mode 100755 index 00000000..17af4474 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/connectivity_plus_windows_plugin.h @@ -0,0 +1,23 @@ +#ifndef FLUTTER_PLUGIN_CONNECTIVITY_WINDOWS_PLUS_PLUGIN_H_ +#define FLUTTER_PLUGIN_CONNECTIVITY_WINDOWS_PLUS_PLUGIN_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void ConnectivityPlusWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_PLUGIN_CONNECTIVITY_PLUS_WINDOWS_PLUGIN_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/network_manager.h b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/network_manager.h new file mode 100755 index 00000000..19394fec --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/include/connectivity_plus/network_manager.h @@ -0,0 +1,50 @@ +#ifndef NETWORK_MANAGER_H +#define NETWORK_MANAGER_H + +// clang-format off +#include +// clang-format on +#include + +#include +#include +#include + +enum class ConnectivityType { None, Ethernet, WiFi, Other, VPN }; + +class NetworkListener; +struct IConnectionPoint; +struct IConnectionPointContainer; +struct INetworkListManager; +struct IUnknown; + +typedef std::function NetworkCallback; + +class NetworkManager { +public: + NetworkManager(); + ~NetworkManager(); + + bool Init(); + void Cleanup(); + + std::set GetConnectivityTypes() const; + + bool StartListen(NetworkCallback pCallback); + void StopListen(); + + bool HasError() const; + int GetError() const; + +private: + std::vector GetConnectedAdapterIds() const; + + DWORD dwCookie = 0; + IUnknown *pUnknown = NULL; + INetworkListManager *pNetworkListManager = NULL; + IConnectionPointContainer *pCPContainer = NULL; + IConnectionPoint *pConnectPoint = NULL; + NetworkListener *pListener = NULL; +}; + +#endif // NETWORK_MANAGER_H diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/network_manager.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/network_manager.cpp new file mode 100755 index 00000000..31822c55 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/connectivity_plus/windows/network_manager.cpp @@ -0,0 +1,252 @@ +// based on +// https://github.com/PurpleI2P/i2pd/blob/master/Win32/Win32NetState.cpp + +/* + * Copyright (c) 2013-2020, The PurpleI2P Project + * + * This file is part of Purple i2pd project and licensed under BSD3 + * + * See full license text in LICENSE file at top of project tree + */ + +#include "include/connectivity_plus/network_manager.h" + +#include +#include +#include + +#include +#include + +class NetworkListener final : public INetworkEvents { +public: + NetworkListener(NetworkCallback pCb) : pCallback(pCb) {} + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) { + AddRef(); + + HRESULT hr = S_OK; + if (IsEqualIID(riid, IID_IUnknown)) { + *ppvObject = (IUnknown *)this; + } else if (IsEqualIID(riid, IID_INetworkEvents)) { + *ppvObject = (INetworkEvents *)this; + } else { + hr = E_NOINTERFACE; + } + return hr; + } + + ULONG STDMETHODCALLTYPE AddRef() { return InterlockedIncrement(&lRef); } + + ULONG STDMETHODCALLTYPE Release() { + LONG lAddend = InterlockedDecrement(&lRef); + if (lRef == 0) { + delete this; + } + return lAddend; + } + + HRESULT STDMETHODCALLTYPE NetworkAdded(GUID networkId) { return S_OK; } + + HRESULT STDMETHODCALLTYPE + NetworkConnectivityChanged(GUID networkId, NLM_CONNECTIVITY newConnectivity) { + Callback(); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE NetworkDeleted(GUID networkId) { return S_OK; } + + HRESULT STDMETHODCALLTYPE + NetworkPropertyChanged(GUID networkId, NLM_NETWORK_PROPERTY_CHANGE flags) { + if (flags & NLM_NETWORK_PROPERTY_CHANGE_CONNECTION) { + Callback(); + } + return S_OK; + } + + void Callback() { + assert(pCallback); + pCallback(); + } + +private: + volatile LONG lRef = 1; + NetworkCallback pCallback = nullptr; +}; + +NetworkManager::NetworkManager() {} + +NetworkManager::~NetworkManager() { + StopListen(); + Cleanup(); +} + +bool NetworkManager::Init() { + CoInitialize(NULL); + + HRESULT hr = CoCreateInstance(CLSID_NetworkListManager, NULL, CLSCTX_ALL, + IID_IUnknown, (void **)&pUnknown); + if (SUCCEEDED(hr)) { + hr = pUnknown->QueryInterface(IID_INetworkListManager, + (void **)&pNetworkListManager); + } + return SUCCEEDED(hr); +} + +void NetworkManager::Cleanup() { + if (pNetworkListManager) { + pNetworkListManager->Release(); + pNetworkListManager = NULL; + } + + if (pUnknown) { + pUnknown->Release(); + pUnknown = NULL; + } + + CoUninitialize(); +} + +std::vector NetworkManager::GetConnectedAdapterIds() const { + std::vector adapterIds; + + IEnumNetworkConnections *connections = NULL; + HRESULT hr = pNetworkListManager->GetNetworkConnections(&connections); + if (hr == S_OK) { + while (true) { + INetworkConnection *connection = NULL; + hr = connections->Next(1, &connection, NULL); + if (hr != S_OK) { + break; + } + + VARIANT_BOOL isConnected = VARIANT_FALSE; + hr = connection->get_IsConnectedToInternet(&isConnected); + if (hr == S_OK && isConnected == VARIANT_TRUE) { + GUID guid; + hr = connection->GetAdapterId(&guid); + if (hr == S_OK) { + adapterIds.push_back(std::move(guid)); + } + } + connection->Release(); + } + connections->Release(); + } + + return adapterIds; +} + +std::set NetworkManager::GetConnectivityTypes() const { + ULONG bufferSize = 15 * 1024; + ULONG flags = GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_FRIENDLY_NAME; + std::vector buffer(bufferSize); + PIP_ADAPTER_ADDRESSES addresses = + reinterpret_cast(&buffer.front()); + DWORD rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); + if (rc == ERROR_BUFFER_OVERFLOW) { + buffer.resize(bufferSize); + addresses = reinterpret_cast(&buffer.front()); + rc = GetAdaptersAddresses(AF_UNSPEC, flags, 0, addresses, &bufferSize); + } + + if (rc != NO_ERROR) { + return {ConnectivityType::None}; + } + + std::vector adapterIds = GetConnectedAdapterIds(); + if (adapterIds.empty()) { + return {ConnectivityType::None}; + } + + std::set connectivities; + for (; addresses != NULL; addresses = addresses->Next) { + NET_LUID luid; + rc = ConvertInterfaceIndexToLuid(addresses->IfIndex, &luid); + if (rc != NO_ERROR) { + continue; + } + + GUID guid; + rc = ConvertInterfaceLuidToGuid(&luid, &guid); + if (rc != NO_ERROR) { + continue; + } + + if (std::find(adapterIds.begin(), adapterIds.end(), guid) != + adapterIds.end()) { + // Read more at + // https://learn.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-ip_adapter_addresses_lh + switch (addresses->IfType) { + case IF_TYPE_ETHERNET_CSMACD: + case IF_TYPE_IEEE1394: + connectivities.insert(ConnectivityType::Ethernet); + break; + case IF_TYPE_IEEE80211: + connectivities.insert(ConnectivityType::WiFi); + break; + case IF_TYPE_TUNNEL: + case IF_TYPE_PPP: + connectivities.insert(ConnectivityType::VPN); + break; + default: + connectivities.insert(ConnectivityType::Other); + break; + } + } + } + + if (connectivities.empty()) { + // If no specific connectivity types were found, return a set containing + // only None + return {ConnectivityType::None}; + } + + // Return the set of detected connectivity types + return connectivities; +} + +bool NetworkManager::StartListen(NetworkCallback pCallback) { + if (!pCallback || pListener) { + return false; + } + + HRESULT hr = pNetworkListManager->QueryInterface( + IID_IConnectionPointContainer, (void **)&pCPContainer); + if (SUCCEEDED(hr)) { + hr = pCPContainer->FindConnectionPoint(IID_INetworkEvents, &pConnectPoint); + if (SUCCEEDED(hr)) { + pListener = new NetworkListener(pCallback); + hr = pConnectPoint->Advise((IUnknown *)pListener, &dwCookie); + if (SUCCEEDED(hr)) { + return true; + } + } + } + return false; +} + +void NetworkManager::StopListen() { + if (pConnectPoint) { + pConnectPoint->Unadvise(dwCookie); + pConnectPoint->Release(); + pConnectPoint = NULL; + dwCookie = 0; + } + + if (pCPContainer) { + pCPContainer->Release(); + pCPContainer = NULL; + } + + if (pListener) { + pListener->Release(); + pListener = NULL; + } +} + +bool NetworkManager::HasError() const { return GetLastError() != 0; } + +int NetworkManager::GetError() const { return GetLastError(); } diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus deleted file mode 120000 index 3eb57813..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/device_info_plus-11.3.0/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/CHANGELOG.md new file mode 100755 index 00000000..8e7f877d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/CHANGELOG.md @@ -0,0 +1,471 @@ +## 11.3.0 + + - **FEAT**(device_info_plus): Add User Device Name in Android (PR [#3437](https://github.com/fluttercommunity/plus_plugins/issues/3437)) ([#3456](https://github.com/fluttercommunity/plus_plugins/issues/3456)). ([8c38a31d](https://github.com/fluttercommunity/plus_plugins/commit/8c38a31d7c1073d7011ec3e3193f6b99b3851ef1)) + +## 11.2.2 + + - **FIX**(device_info_plus): Replace throwing exception with returning default values on Windows ([#3445](https://github.com/fluttercommunity/plus_plugins/issues/3445)). ([084730f8](https://github.com/fluttercommunity/plus_plugins/commit/084730f82436b474b31b16f6dc2d7b90585e899f)) + - **DOCS**(device_info_plus): Update the documentation URL for property descriptions. ([#3441](https://github.com/fluttercommunity/plus_plugins/issues/3441)). ([743bec62](https://github.com/fluttercommunity/plus_plugins/commit/743bec626c909fdc8ba6d087006568cca60563d8)) + +## 11.2.1 + + - **FIX**(device_info_plus): Resolve compilation issues with SPM enabled ([#3405](https://github.com/fluttercommunity/plus_plugins/issues/3405)). ([3f098c30](https://github.com/fluttercommunity/plus_plugins/commit/3f098c30320e1595c06b093e8eb9827a44435c5d)) + - **FIX**(device_info_plus): device memory null error on Safari and Firefox ([#3401](https://github.com/fluttercommunity/plus_plugins/issues/3401)). ([2b7cb088](https://github.com/fluttercommunity/plus_plugins/commit/2b7cb0888cd725dc69e409590861fe8118058c4d)) + - **FIX**(device_info_plus): add @Suppress(deprecate) to Build.SERIAL ([#3402](https://github.com/fluttercommunity/plus_plugins/issues/3402)). ([8e70d3f3](https://github.com/fluttercommunity/plus_plugins/commit/8e70d3f33d5f1c005dbb1aef733a8a8578989bac)) + +## 11.2.0 + + - **REFACTOR**(all): Use range of flutter_lints for broader compatibility ([#3371](https://github.com/fluttercommunity/plus_plugins/issues/3371)). ([8a303add](https://github.com/fluttercommunity/plus_plugins/commit/8a303add3dee1acb8bac5838246490ed8a0fe408)) + - **FIX**(device_info_plus): fix the error in the e2e test. ([#3382](https://github.com/fluttercommunity/plus_plugins/issues/3382)). ([3d06bf0e](https://github.com/fluttercommunity/plus_plugins/commit/3d06bf0ed8f1029df1230e4be6e75537abfcb19f)) + - **FIX**(device_info_plus): Set correct Flutter and Dart versions requirements ([#3362](https://github.com/fluttercommunity/plus_plugins/issues/3362)). ([77861523](https://github.com/fluttercommunity/plus_plugins/commit/778615231c376c829d6241e7988f15a77bcaeb55)) + - **FEAT**(device_info_plus): Return model name for iOS and MacOS devices ([#3358](https://github.com/fluttercommunity/plus_plugins/issues/3358)). ([63ca4cd8](https://github.com/fluttercommunity/plus_plugins/commit/63ca4cd8127e010650468a79532dd3a6047d2b31)) + - **FEAT**(device_info_plus): Add the isiOSAppOnMac property for the iOS platform. ([#3383](https://github.com/fluttercommunity/plus_plugins/issues/3383)). ([e9077845](https://github.com/fluttercommunity/plus_plugins/commit/e9077845342023d325280985234b6a09d245ac02)) + +## 11.1.1 + + - **FIX**(device_info_plus): Update privacy manifest paths ([#3347](https://github.com/fluttercommunity/plus_plugins/issues/3347)). ([46df2302](https://github.com/fluttercommunity/plus_plugins/commit/46df23023a5ba6c98edd31d5fd06bec5df40bd3b)) + +## 11.1.0 + + - **FIX**(device_info_plus): Ignore `MissingPermission` lint error on Android ([#3317](https://github.com/fluttercommunity/plus_plugins/issues/3317)). ([6469523f](https://github.com/fluttercommunity/plus_plugins/commit/6469523fb14f32f7aa23892183693a8f502992d3)) + - **FEAT**(device_info_plus): Add Swift Package Manager support ([#3167](https://github.com/fluttercommunity/plus_plugins/issues/3167)). ([6a347cb1](https://github.com/fluttercommunity/plus_plugins/commit/6a347cb106182d68329cd32827938e26bc7e7b00)) + +## 11.0.0 + +> Note: This release has breaking changes. + + - **FIX**(all): Clean up macOS Privacy Manifests ([#3268](https://github.com/fluttercommunity/plus_plugins/issues/3268)). ([d7b98ebd](https://github.com/fluttercommunity/plus_plugins/commit/d7b98ebd7d39b0143931f5cc6e627187576223dc)) + - **FIX**(all): Add macOS Privacy Manifests ([#3251](https://github.com/fluttercommunity/plus_plugins/issues/3251)). ([bf5dad2a](https://github.com/fluttercommunity/plus_plugins/commit/bf5dad2ad249605055bcbd5f663e42569df12d64)) + - **FIX**(device_info_plus): Fix type cast of digitalProductId on windows ([#3188](https://github.com/fluttercommunity/plus_plugins/issues/3188)). ([91f48a6b](https://github.com/fluttercommunity/plus_plugins/commit/91f48a6bc7d11c4238c9539ca06e6fa768995580)) + - **BREAKING** **FIX**(device_info_plus): fixed webasm compliance ([#3254](https://github.com/fluttercommunity/plus_plugins/issues/3254)). ([e35e2123](https://github.com/fluttercommunity/plus_plugins/commit/e35e2123451fc103bbb6f6d94f71ebced2ae8af5)) + +## 10.1.2 + + - **DOCS**(device_info_plus): Update plugin requirements in README ([#3162](https://github.com/fluttercommunity/plus_plugins/issues/3162)). ([6cfa950f](https://github.com/fluttercommunity/plus_plugins/commit/6cfa950f66fec649093b6c44755dc06a3a23319e)) + +## 10.1.1 + + - **CHORE**(device_info_plus): Use `>=0.5.0 < 2.0.0` version range for package:web. + - **FIX**(device_info_plus): fix integration_test iOS ([#2958](https://github.com/fluttercommunity/plus_plugins/issues/2958)). ([93ab854e](https://github.com/fluttercommunity/plus_plugins/commit/93ab854ee76a3de48387b6c54ddaeccb01cf49a9)) + - **REFACTOR**(all): Remove website files, configs, mentions ([#3018](https://github.com/fluttercommunity/plus_plugins/issues/3018)). ([ecc57146](https://github.com/fluttercommunity/plus_plugins/commit/ecc57146aa8c6b1c9c332169d3cc2205bc4a700f)) + - **FIX**(all): changed homepage url in pubspec.yaml ([#3099](https://github.com/fluttercommunity/plus_plugins/issues/3099)). ([66613656](https://github.com/fluttercommunity/plus_plugins/commit/66613656a85c176ba2ad337e4d4943d1f4171129)) + +## 10.1.0 + + - **REFACTOR**(device_info_plus): Migrate Android example to use the new plugins declaration ([#2769](https://github.com/fluttercommunity/plus_plugins/issues/2769)). ([6103b155](https://github.com/fluttercommunity/plus_plugins/commit/6103b1559d6f9383bd66460bf7717afeeeb51d86)) + - **FIX**(device_info_plus): WASM-compatible conditional imports ([#2826](https://github.com/fluttercommunity/plus_plugins/issues/2826)). ([11200cf4](https://github.com/fluttercommunity/plus_plugins/commit/11200cf4eb38bfa6bc83e955a3ceff7b8fc72493)) + - **FEAT**(device_info_plus): Add isLowRamDevice property to AndroidDeviceInfo ([#2765](https://github.com/fluttercommunity/plus_plugins/issues/2765)). ([1376b035](https://github.com/fluttercommunity/plus_plugins/commit/1376b0359fd39172cfb54595178313c73f5d1942)) + - **DOCS**(device_info_plus): Add iOS name property entitlements info ([#2756](https://github.com/fluttercommunity/plus_plugins/issues/2756)). ([d21f285a](https://github.com/fluttercommunity/plus_plugins/commit/d21f285a1d26e7a512c4a9aea579de9680a6ca48)) + +## 10.0.1 + +> Note: This release has breaking changes. + +In this release plugin migrated to package:web, meaning that it now supports WASM! + +Plugin now requires the following: +- Flutter >=3.19.0 +- Dart >=3.3.0 +- compileSDK 34 for Android part +- Java 17 for Android part +- Gradle 8.4 for Android part +- + - **BREAKING** **REFACTOR**(device_info_plus): bump MACOSX_DEPLOYMENT_TARGET from 10.11 to 10.14 ([#2589](https://github.com/fluttercommunity/plus_plugins/issues/2589)). ([1c586abf](https://github.com/fluttercommunity/plus_plugins/commit/1c586abf7ee351927242a70cb88e2e36140cec9e)) + - **BREAKING** **FIX**(device_info_plus): Remove Display Metrics from Android Device Info ([#2731](https://github.com/fluttercommunity/plus_plugins/issues/2731)). ([c5af3322](https://github.com/fluttercommunity/plus_plugins/commit/c5af332207e44902ac92765da72d2acb213fae91)) + - **BREAKING** **FEAT**(device_info_plus): migrate to package:web ([#2624](https://github.com/fluttercommunity/plus_plugins/issues/2624)). ([154e76ca](https://github.com/fluttercommunity/plus_plugins/commit/154e76ca2f9e8c1ccdaa6e2076426002c9d372a3)) + - **BREAKING** **BUILD**(device_info_plus): Target Java 17 on Android ([#2725](https://github.com/fluttercommunity/plus_plugins/issues/2725)). ([aa826dea](https://github.com/fluttercommunity/plus_plugins/commit/aa826deac5ef8136ce922f5823be2e7f90f828e9)) + - **BREAKING** **BUILD**(device_info_plus): Update to target and compile SDK 34 ([#2704](https://github.com/fluttercommunity/plus_plugins/pull/2704)). ([a3cd72f](https://github.com/fluttercommunity/plus_plugins/commit/a3cd72f86ba47f43c507f8b83f89aac7519404de)) + - **FIX**(device_info_plus): remove unnecessary print ([#2607](https://github.com/fluttercommunity/plus_plugins/issues/2607)). ([5d515816](https://github.com/fluttercommunity/plus_plugins/commit/5d5158169f75c50f15588c10e07af2e25f950c23)) + - **FIX**(device_info_plus): return type of isPhysicalDevice as boolean for ios ([#2508](https://github.com/fluttercommunity/plus_plugins/issues/2508)). ([e3a983bb](https://github.com/fluttercommunity/plus_plugins/commit/e3a983bbf0b0bb70c7c50835ddb7f3c4a46b7122)) + - **FIX**(device_info_plus): Add iOS Privacy Info ([#2582](https://github.com/fluttercommunity/plus_plugins/issues/2582)). ([34fe31eb](https://github.com/fluttercommunity/plus_plugins/commit/34fe31eb29e21fa9ea336e61d8df6858eb441a00)) + - **FEAT**(device_info_plus): Update min iOS target to 12 ([#2658](https://github.com/fluttercommunity/plus_plugins/issues/2658)). ([a3436100](https://github.com/fluttercommunity/plus_plugins/commit/a3436100fabd04a4d4db7ac09128b5b5962579d3)) + - **FEAT**(device_info_plus): LinuxDeviceInfo toString method ([#2652](https://github.com/fluttercommunity/plus_plugins/issues/2652)). ([f2fbcdb8](https://github.com/fluttercommunity/plus_plugins/commit/f2fbcdb813b62dcb76c18b00e51383e6643a93ed)) + +## 10.0.0 + +> Note: This release was retracted due to ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). + +## 9.1.2 + + - **FIX**(device_info_plus): fix crash on non-standard Digital Product IDs ([#2537](https://github.com/fluttercommunity/plus_plugins/issues/2537)). ([7b318b5c](https://github.com/fluttercommunity/plus_plugins/commit/7b318b5cd8496cf7d31c62314eb9bae17f9ef8d6)) + +## 9.1.1 + + - **FIX**(device_info_plus): Fix deprecation warning on MacOS ([#2377](https://github.com/fluttercommunity/plus_plugins/issues/2377)). ([56a6d0ff](https://github.com/fluttercommunity/plus_plugins/commit/56a6d0ff3752570de89f00876eb7181d662a0465)) + +## 9.1.0 + +> Info: This release is a replacement for release 10.0.0, which was retracted due to issue ([#2251](https://github.com/fluttercommunity/plus_plugins/issues/2251)). As breaking change was reverted the major release was also reverted in favor of this one. + + - **FIX**(device_info_plus): Change Kotlin version from 1.9.10 to 1.7.22 ([#2256](https://github.com/fluttercommunity/plus_plugins/issues/2256)). ([313ec2c3](https://github.com/fluttercommunity/plus_plugins/commit/313ec2c328f34b278f197ee1f2d896f8820ac789)) + - **FIX**(device_info_plus): Revert bump compileSDK to 34 ([#2230](https://github.com/fluttercommunity/plus_plugins/issues/2230)). ([2ba5b054](https://github.com/fluttercommunity/plus_plugins/commit/2ba5b054948f48a9aae72c8a63b39f6536ab678d)) + - **FIX**(device_info_plus): Update exports to avoid web compatibility issues ([#2028](https://github.com/fluttercommunity/plus_plugins/issues/2028)). ([6c216053](https://github.com/fluttercommunity/plus_plugins/commit/6c2160537dc51493adc5bf22cd480a52582845b0)) + - **FIX**(device_info_plus): Regenerate iOS and MacOS example apps ([#1868](https://github.com/fluttercommunity/plus_plugins/issues/1868)). ([6e1111ac](https://github.com/fluttercommunity/plus_plugins/commit/6e1111acff40fef6f77fe2561810d679bafe938c)) + - **FEAT**(device_info_plus): Remove deprecated VALID_ARCHS iOS property ([#2022](https://github.com/fluttercommunity/plus_plugins/issues/2022)). ([13053295](https://github.com/fluttercommunity/plus_plugins/commit/13053295137201b34a6bf52e494ccf77e0321b18)) + - **DOCS**(device_info_plus): Add note about arch returned value on MacOS ([#2220](https://github.com/fluttercommunity/plus_plugins/issues/2220)). ([80409e2a](https://github.com/fluttercommunity/plus_plugins/commit/80409e2ab13a6379b9101034ad453517151a719a)) + - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) + +## 9.0.3 + + - **FIX**(device_info_plus): Regenerate iOS and MacOS example apps ([#1868](https://github.com/fluttercommunity/plus_plugins/issues/1868)). ([6e1111ac](https://github.com/fluttercommunity/plus_plugins/commit/6e1111acff40fef6f77fe2561810d679bafe938c)) + - **DOCS**(all): Fix example links on pub.dev ([#1863](https://github.com/fluttercommunity/plus_plugins/issues/1863)). ([d726035a](https://github.com/fluttercommunity/plus_plugins/commit/d726035ad7631d5a1397d0a2e5df23dc7e30a4f7)) + +## 9.0.2 + + - **DOCS**(device_info_plus): Add links to Android and iOS docs to every field ([#1857](https://github.com/fluttercommunity/plus_plugins/issues/1857)). ([89eb5217](https://github.com/fluttercommunity/plus_plugins/commit/89eb52177c90d5453ba512e73472536fc8a03c9a)) + +## 9.0.1 + + - **FIX**: Add jvm target compatibility to Kotlin plugins ([#1798](https://github.com/fluttercommunity/plus_plugins/issues/1798)). ([1b7dc432](https://github.com/fluttercommunity/plus_plugins/commit/1b7dc432ffb8d0474c9be6339d20b5a2cbcbab3f)) + - **DOCS**(all): Update READMEs ([#1828](https://github.com/fluttercommunity/plus_plugins/issues/1828)). ([57d9c884](https://github.com/fluttercommunity/plus_plugins/commit/57d9c8845edfc81fdbabcef9eb1d1ca450e62e7d)) + - **CHORE**(device_info_plus): Win32 dependency upgrade ([#1805](https://github.com/fluttercommunity/plus_plugins/pull/1805)). ([3f68800](https://github.com/fluttercommunity/plus_plugins/commit/c8f7b6342a7c51eafafae95792775505d2b52ce9)) + +## 9.0.0 + +> Note: This release has breaking changes. + + - **CHORE**(device_info_plus): Update Flutter dependencies, set Flutter >=3.3.0 and Dart to >=2.18.0 <4.0.0 + - **BREAKING** **FIX**(all): Add support of namespace property to support Android Gradle Plugin (AGP) 8 (#1727). Projects with AGP < 4.2 are not supported anymore. It is highly recommended to update at least to AGP 7.0 or newer. + - **BREAKING** **CHORE**(device_info_plus): Bump min Android to 4.4 (API 19) and iOS to 11, update podspec file (#1781). + - **REFACTOR**(device_info_plus): Refactor Windows implementation (#1772). + - **REFACTOR**(device_info_plus): Remove redundant checks for PRODUCT strings with sdk (#1745). + - **REFACTOR**(device_info_plus): Declare proper nullability for iOS properties (#1728). + +## 8.2.2 + + - **FIX**(all): Revert addition of namespace to avoid build fails on old AGPs (#1725). + +## 8.2.1 + + - **FIX**(device_info_plus): Add compatibility with AGP 8 (Android Gradle Plugin) (#1702). + +## 8.2.0 + + - **REFACTOR**(all): Remove all manual dependency_overrides (#1628). + - **FEAT**(device_info_plus): add major, minor and patch versions to macos (#1649). + +## 8.1.0 + + - **FEAT**: Add serialNumber property to AndroidDeviceInfo (#1349). + - **DOCS**: Updates for READMEs and website pages (#1389). + - **DOCS**: Explain how to get serial number on Android (#1390). + - **DOCS**: Add info about iOS 16 changes to device name (#1356). + +## 8.0.0 + +> Note: This release has breaking changes. + + - **DOCS**: Document toMap deprecation (#1292). + - **BREAKING** **FEAT**: refactor of device_info_plus platform implementation (#1293). + +## 7.0.1 + + - **FIX**: Increase min Flutter version to fix dartPluginClass registration (#1275). + +## 7.0.0 + +> Note: This release has breaking changes. + + - **REFACTOR**: Migrate Android part to Kotlin, update Android dependencies (#1245). + - **FIX**: add `@Deprecated` annotation to `toMap` method (#1142). + - **DOCS**: Add info about Android properties availability, update API docs links (#1243). + - **BREAKING** **REFACTOR**: two-package federated architecture (#1228). + +## 6.0.0 + +> Note: This release has breaking changes. + + - **BREAKING** **FEAT**: Add support of Android display metrics (#829). + +## 5.0.5 + + - Update a dependency to the latest release. + +## 5.0.4 + + - **FIX**: fixed wrong dependency version #1175. + +## 5.0.3 + + - **FIX**: fix version dependency. + +## 5.0.2 + + - **CHORE**: Version tagging using melos. + +## 5.0.1 + +- Fixing federated plugin architecture versions. + +## 5.0.0 + +- Re-introduce: Added more information to `WindowsDeviceInfo`. +- device_info_plus_platform_interface to 4.0.0 + +## 4.1.3 + +- Detects iOS simulator device id instead of simulator's underlying architecture. + +## 4.1.2 + +- Redo changes in 4.1.0 +- device_info_plus_platform_interface to 3.0.0 + +## 4.1.1 + +- Revert changes in 4.1.0 + +## 4.1.0 + +- Remove `androidId` (that already got removed from the method channel in 4.0.0, thus always returned null) +- There is a **new, separate [pub.dev package](https://pub.dev/packages/android_id) for getting the correct `androidId`** + +## 4.0.3 + +- Reverted changes in 4.0.2 + +## 4.0.2 + +- Added more information to `WindowsDeviceInfo`. + +## 4.0.1 + +- Update dependencies + +## 4.0.0 + +- **Breaking change** Remove `AndroidId` getter to avoid Google Play policies violations +- Update flutter_lints to 2.0.1 +- Remove explicit `test` dependency to use `flutter_test` from Flutter SDK + +## 3.2.4 + +- Update the description of getAndroidId method + +## 3.2.3 + +- Fix crash on macOS running on Apple M1 + +## 3.2.2 + +- Fix embedding issue in example +- Update Android dependencies in example + +## 3.2.1 + +- iOS: fix `identifierForVendor` (can be `null` in rare circumstances) +- Use automatic plugin registration on Linux and Windows +- Fix warnings when building for macOS + +## 3.2.0 + +- add `deviceInfo` + +## 3.1.1 + +- add toMap to WebBrowserInfo + +## 3.1.0 + +- add System GUID to MacOS + +## 3.0.1 + +- Upgrade Android compile SDK version +- Several code improvements + +## 3.0.0 + +- Remove deprecated method `registerWith` (of Android v1 embedding) + +## 2.2.0 + +- migrate integration_test to flutter sdk + +## 2.1.0 + +- add toMap to models + +## 2.0.1 + +- Android: migrate to mavenCentral + +## 2.0.0 + +- WebBrowserInfo properties are now nullable + +## 1.0.1 + +- Improve documentation + +## 1.0.0 + +- Migrated to null safety +- Update dependencies. + +## 0.7.2 + +- Update dependencies. + +## 0.7.1 + +- Fix macOS support. + +## 0.7.0 + +- Add macOS support via `device_info_plus_macos`. + +## 0.6.0 + +- Rename method channel to avoid conflicts. + +## 0.5.0 + +- Transfer to plus-plugins monorepo + +## 0.4.2+8 + +- Transfer package to Flutter Community under new name `device_info_plus`. + +## 0.4.2+7 + +- Port device_info plugin to use platform interface. + +## 0.4.2+6 + +- Moved everything from device_info to device_info/device_info + +## 0.4.2+5 + +- Update package:e2e reference to use the local version in the flutter/plugins + repository. + +## 0.4.2+4 + +Update lower bound of dart dependency to 2.1.0. + +## 0.4.2+3 + +- Declare API stability and compatibility with `1.0.0` (more details at: https://github.com/flutter/flutter/wiki/Package-migration-to-1.0.0). + +## 0.4.2+2 + +- Fix CocoaPods podspec lint warnings. + +## 0.4.2+1 + +- Bump the minimum Flutter version to 1.12.13+hotfix.5. +- Remove deprecated API usage warning in AndroidIntentPlugin.java. +- Migrates the Android example to V2 embedding. +- Bumps AGP to 3.6.1. + +## 0.4.2 + +- Add systemFeatures to AndroidDeviceInfo. + +## 0.4.1+5 + +- Make the pedantic dev_dependency explicit. + +## 0.4.1+4 + +- Remove the deprecated `author:` field from pubspec.yaml +- Migrate the plugin to the pubspec platforms manifest. +- Require Flutter SDK 1.10.0 or greater. + +## 0.4.1+3 + +- Fix pedantic errors. Adds some missing documentation and fixes unawaited + futures in the tests. + +## 0.4.1+2 + +- Remove AndroidX warning. + +## 0.4.1+1 + +- Include lifecycle dependency as a compileOnly one on Android to resolve + potential version conflicts with other transitive libraries. + +## 0.4.1 + +- Support the v2 Android embedding. +- Update to AndroidX. +- Migrate to using the new e2e test binding. +- Add a e2e test. + +## 0.4.0+4 + +- Define clang module for iOS. + +## 0.4.0+3 + +- Update and migrate iOS example project. + +## 0.4.0+2 + +- Bump minimum Flutter version to 1.5.0. +- Add missing template type parameter to `invokeMethod` calls. +- Replace invokeMethod with invokeMapMethod wherever necessary. + +## 0.4.0+1 + +- Log a more detailed warning at build time about the previous AndroidX + migration. + +## 0.4.0 + +- **Breaking change**. Migrate from the deprecated original Android Support + Library to AndroidX. This shouldn't result in any functional changes, but it + requires any Android apps using this plugin to [also + migrate](https://developer.android.com/jetpack/androidx/migrate) if they're + using the original support library. + +## 0.3.0 + +- Added ability to get Android ID for Android devices + +## 0.2.1 + +- Updated Gradle tooling to match Android Studio 3.1.2. + +## 0.2.0 + +- **Breaking change**. Set SDK constraints to match the Flutter beta release. + +## 0.1.2 + +- Fixed Dart 2 type errors. + +## 0.1.1 + +- Simplified and upgraded Android project template to Android SDK 27. +- Updated package description. + +## 0.1.0 + +- **Breaking change**. Upgraded to Gradle 4.1 and Android Studio Gradle plugin + 3.0.1. Older Flutter projects need to upgrade their Gradle setup as well in + order to use this version of the plugin. Instructions can be found + [here](https://github.com/flutter/flutter/wiki/Updating-Flutter-projects-to-Gradle-4.1-and-Android-Studio-Gradle-plugin-3.0.1). + +## 0.0.5 + +- Added FLT prefix to iOS types + +## 0.0.4 + +- Fixed Java/Dart communication error with empty lists + +## 0.0.3 + +- Added support for utsname + +## 0.0.2 + +- Fixed broken type comparison +- Added "isPhysicalDevice" field, detecting emulators/simulators + +## 0.0.1 + +- Implements platform-specific device/OS properties diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/LICENSE new file mode 100755 index 00000000..7b995420 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/LICENSE @@ -0,0 +1,27 @@ +Copyright 2017 The Chromium Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/README.md new file mode 100755 index 00000000..fdfd7da5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/README.md @@ -0,0 +1,76 @@ +# device_info_plus + +[![pub package](https://img.shields.io/pub/v/device_info_plus.svg)](https://pub.dev/packages/device_info_plus) +[![pub points](https://img.shields.io/pub/points/device_info_plus?color=2E8B57&label=pub%20points)](https://pub.dev/packages/device_info_plus/score) +[![device_info_plus](https://github.com/fluttercommunity/plus_plugins/actions/workflows/device_info_plus.yaml/badge.svg)](https://github.com/fluttercommunity/plus_plugins/actions/workflows/device_info_plus.yaml) + +[](https://flutter.dev/docs/development/packages-and-plugins/favorites) + +Get current device information from within the Flutter application. + +## Platform Support + +| Android | iOS | MacOS | Web | Linux | Windows | +| :-----: | :-: | :---: | :-: | :---: | :-----: | +| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | + +## Requirements + +- Flutter >=3.22.0 +- Dart >=3.4.0 <4.0.0 +- iOS >=12.0 +- MacOS >=10.14 +- Android `compileSDK` 34 +- Java 17 +- Android Gradle Plugin >=8.3.0 +- Gradle wrapper >=8.4 + +# Usage + +Import `package:device_info_plus/device_info_plus.dart`, instantiate `DeviceInfoPlugin` +and use the Android and iOS, Web getters to get platform-specific device +information. + +Example: + +```dart +import 'package:device_info_plus/device_info_plus.dart'; + +DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); +AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; +print('Running on ${androidInfo.model}'); // e.g. "Moto G (4)" + +IosDeviceInfo iosInfo = await deviceInfo.iosInfo; +print('Running on ${iosInfo.utsname.machine}'); // e.g. "iPod7,1" + +WebBrowserInfo webBrowserInfo = await deviceInfo.webBrowserInfo; +print('Running on ${webBrowserInfo.userAgent}'); // e.g. "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0" +``` + +The plugin provides a `data` method that returns platform-specific device +information in a generic way, which can be used for crash-reporting purposes. + +However, the data provided by this `data` method is currently not serializable +(i.e. it is not 100% JSON compatible) and shouldn't be treated as such. + +```dart +import 'package:device_info_plus/device_info_plus.dart'; + +final deviceInfoPlugin = DeviceInfoPlugin(); +final deviceInfo = await deviceInfoPlugin.deviceInfo; +final allInfo = deviceInfo.data; +``` + +### Android + +To get serial number on Android your app needs to meet one of official [requirements](https://developer.android.com/reference/android/os/Build#getSerial()). +In case the app doesn't meet any of requirements plugin will return `unknown`. + +### iOS + +The `name` property exposes the assigned device name by the owner. This value is obtained from the property `UIDevice.current.name`. +This property requires special entitlement [com.apple.developer.device-information.user-assigned-device-name](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_device-information_user-assigned-device-name) in iOS 16 and later, otherwise, the property `name` will always be `iPad` or `iPhone`. + +## Learn more + +- [API Documentation](https://pub.dev/documentation/device_info_plus/latest/device_info_plus/device_info_plus-library.html) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/build.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/build.gradle new file mode 100755 index 00000000..5213cd0a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/build.gradle @@ -0,0 +1,53 @@ +group 'dev.fluttercommunity.plus.device_info' +version '1.0-SNAPSHOT' + +buildscript { + ext.kotlin_version = '1.7.22' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:8.3.1' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +rootProject.allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + compileSdk 34 + + namespace 'dev.fluttercommunity.plus.device_info' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = 17 + } + + defaultConfig { + minSdk 19 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + lintOptions { + disable 'InvalidPackage', 'MissingPermission' + } + + dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle.properties new file mode 100755 index 00000000..8bd86f68 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536M diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..e411586a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/settings.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/settings.gradle new file mode 100755 index 00000000..0e75718c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'device_info' diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/AndroidManifest.xml new file mode 100755 index 00000000..412ea27f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/DeviceInfoPlusPlugin.kt b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/DeviceInfoPlusPlugin.kt new file mode 100755 index 00000000..3ba8c921 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/DeviceInfoPlusPlugin.kt @@ -0,0 +1,32 @@ +package dev.fluttercommunity.plus.device_info + +import android.app.ActivityManager +import android.content.Context +import android.content.pm.PackageManager +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MethodChannel + +/** DeviceInfoPlusPlugin */ +class DeviceInfoPlusPlugin : FlutterPlugin { + + private lateinit var methodChannel: MethodChannel + + override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { + setupMethodChannel(binding.binaryMessenger, binding.applicationContext) + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + methodChannel.setMethodCallHandler(null) + } + + private fun setupMethodChannel(messenger: BinaryMessenger, context: Context) { + methodChannel = MethodChannel(messenger, "dev.fluttercommunity.plus/device_info") + val packageManager: PackageManager = context.packageManager + val activityManager: ActivityManager = + context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + val contentResolver = context.contentResolver + val handler = MethodCallHandlerImpl(packageManager, activityManager, contentResolver) + methodChannel.setMethodCallHandler(handler) + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt new file mode 100755 index 00000000..4cfdf4f9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/android/src/main/kotlin/dev/fluttercommunity/plus/device_info/MethodCallHandlerImpl.kt @@ -0,0 +1,114 @@ +package dev.fluttercommunity.plus.device_info + +import android.app.ActivityManager +import android.content.ContentResolver +import android.content.pm.FeatureInfo +import android.content.pm.PackageManager +import android.os.Build +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import kotlin.collections.HashMap +import android.provider.Settings + +/** + * The implementation of [MethodChannel.MethodCallHandler] for the plugin. Responsible for + * receiving method calls from method channel. + */ +internal class MethodCallHandlerImpl( + private val packageManager: PackageManager, + private val activityManager: ActivityManager, + private val contentResolver: ContentResolver, +) : MethodCallHandler { + + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { + if (call.method.equals("getDeviceInfo")) { + val build: MutableMap = HashMap() + + build["board"] = Build.BOARD + build["bootloader"] = Build.BOOTLOADER + build["brand"] = Build.BRAND + build["device"] = Build.DEVICE + build["display"] = Build.DISPLAY + build["fingerprint"] = Build.FINGERPRINT + build["hardware"] = Build.HARDWARE + build["host"] = Build.HOST + build["id"] = Build.ID + build["manufacturer"] = Build.MANUFACTURER + build["model"] = Build.MODEL + build["product"] = Build.PRODUCT + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { + build["name"] = Settings.Global.getString(contentResolver, Settings.Global.DEVICE_NAME) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + build["supported32BitAbis"] = listOf(*Build.SUPPORTED_32_BIT_ABIS) + build["supported64BitAbis"] = listOf(*Build.SUPPORTED_64_BIT_ABIS) + build["supportedAbis"] = listOf(*Build.SUPPORTED_ABIS) + } else { + build["supported32BitAbis"] = emptyList() + build["supported64BitAbis"] = emptyList() + build["supportedAbis"] = emptyList() + } + + build["tags"] = Build.TAGS + build["type"] = Build.TYPE + build["isPhysicalDevice"] = !isEmulator + build["systemFeatures"] = getSystemFeatures() + + val version: MutableMap = HashMap() + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + version["baseOS"] = Build.VERSION.BASE_OS + version["previewSdkInt"] = Build.VERSION.PREVIEW_SDK_INT + version["securityPatch"] = Build.VERSION.SECURITY_PATCH + } + version["codename"] = Build.VERSION.CODENAME + version["incremental"] = Build.VERSION.INCREMENTAL + version["release"] = Build.VERSION.RELEASE + version["sdkInt"] = Build.VERSION.SDK_INT + build["version"] = version + build["isLowRamDevice"] = activityManager.isLowRamDevice + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + build["serialNumber"] = try { + Build.getSerial() + } catch (ex: SecurityException) { + Build.UNKNOWN + } + } else { + @Suppress("DEPRECATION") + build["serialNumber"] = Build.SERIAL + } + + result.success(build) + } else { + result.notImplemented() + } + } + + private fun getSystemFeatures(): List { + val featureInfos: Array = packageManager.systemAvailableFeatures + return featureInfos + .filterNot { featureInfo -> featureInfo.name == null } + .map { featureInfo -> featureInfo.name } + } + + /** + * A simple emulator-detection based on the flutter tools detection logic and a couple of legacy + * detection systems + */ + private val isEmulator: Boolean + get() = ((Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) + || Build.FINGERPRINT.startsWith("generic") + || Build.FINGERPRINT.startsWith("unknown") + || Build.HARDWARE.contains("goldfish") + || Build.HARDWARE.contains("ranchu") + || Build.MODEL.contains("google_sdk") + || Build.MODEL.contains("Emulator") + || Build.MODEL.contains("Android SDK built for x86") + || Build.MANUFACTURER.contains("Genymotion") + || Build.PRODUCT.contains("sdk") + || Build.PRODUCT.contains("vbox86p") + || Build.PRODUCT.contains("emulator") + || Build.PRODUCT.contains("simulator")) +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/README.md new file mode 100755 index 00000000..53c05c2c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/README.md @@ -0,0 +1,5 @@ +# device_info_example + +Demonstrates how to use the `device_info_plus` plugin[1]. + +[1]: ../ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/build.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/build.gradle new file mode 100755 index 00000000..1e70360c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/build.gradle @@ -0,0 +1,66 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + compileSdk 34 + + namespace 'io.flutter.plugins.deviceinfoexample.example' + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = 17 + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + applicationId "io.flutter.plugins.deviceinfoexample.example" + minSdk 21 + targetSdk 34 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + 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.debug + } + } +} + +flutter { + source '../..' +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/debug/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/debug/AndroidManifest.xml new file mode 100755 index 00000000..175e81dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/AndroidManifest.xml new file mode 100755 index 00000000..d75557c5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/kotlin/io/flutter/plugins/deviceinfoexample/example/MainActivity.kt b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/kotlin/io/flutter/plugins/deviceinfoexample/example/MainActivity.kt new file mode 100755 index 00000000..e2bd9925 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/kotlin/io/flutter/plugins/deviceinfoexample/example/MainActivity.kt @@ -0,0 +1,21 @@ +package io.flutter.plugins.deviceinfoexample.example + +import android.os.Build +import android.os.Bundle +import android.os.StrictMode +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + // Ensures correct use of Activity Context to obtain the WindowManager + StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder() + .detectIncorrectContextUse() + .penaltyLog() + .penaltyDeath() + .build()) + } + super.onCreate(savedInstanceState) + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/drawable/launch_background.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100755 index 00000000..304732f8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100755 index 00000000..db77bb4b Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100755 index 00000000..17987b79 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100755 index 00000000..09d43914 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100755 index 00000000..d5f1c8d3 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100755 index 00000000..4d6372ee Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/values/styles.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/values/styles.xml new file mode 100755 index 00000000..1f83a33f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/profile/AndroidManifest.xml b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/profile/AndroidManifest.xml new file mode 100755 index 00000000..175e81dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/build.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/build.gradle new file mode 100755 index 00000000..bc157bd1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/build.gradle @@ -0,0 +1,18 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle.properties new file mode 100755 index 00000000..d9cf55df --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100755 index 00000000..448814c7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue Oct 05 15:15:38 CEST 2021 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/settings.gradle b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/settings.gradle new file mode 100755 index 00000000..fa3b4d08 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/android/settings.gradle @@ -0,0 +1,25 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.3.1" apply false + id "org.jetbrains.kotlin.android" version "1.9.23" apply false +} + +include ":app" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/integration_test/device_info_plus_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/integration_test/device_info_plus_test.dart new file mode 100755 index 00000000..2cb0a980 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/integration_test/device_info_plus_test.dart @@ -0,0 +1,236 @@ +// Copyright 2019, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + late IosDeviceInfo iosInfo; + late AndroidDeviceInfo androidInfo; + late WebBrowserInfo webBrowserInfo; + late WindowsDeviceInfo windowsInfo; + late LinuxDeviceInfo linuxInfo; + late MacOsDeviceInfo macosInfo; + late BaseDeviceInfo deviceInfo; + + setUpAll(() async { + final deviceInfoPlugin = DeviceInfoPlugin(); + if (kIsWeb) { + webBrowserInfo = await deviceInfoPlugin.webBrowserInfo; + } else { + if (Platform.isIOS) { + iosInfo = await deviceInfoPlugin.iosInfo; + } else if (Platform.isAndroid) { + androidInfo = await deviceInfoPlugin.androidInfo; + } else if (Platform.isWindows) { + windowsInfo = await deviceInfoPlugin.windowsInfo; + } else if (Platform.isLinux) { + linuxInfo = await deviceInfoPlugin.linuxInfo; + } else if (Platform.isMacOS) { + macosInfo = await deviceInfoPlugin.macOsInfo; + } + } + + deviceInfo = await deviceInfoPlugin.deviceInfo; + }); + + testWidgets('Can get non-null device model', (WidgetTester tester) async { + if (kIsWeb) { + expect(webBrowserInfo.userAgent, isNotNull); + expect(deviceInfo, same(webBrowserInfo)); + } else { + if (Platform.isIOS) { + expect(iosInfo.model, isNotNull); + expect(deviceInfo, same(iosInfo)); + } else if (Platform.isAndroid) { + expect(androidInfo.model, isNotNull); + expect(deviceInfo, same(androidInfo)); + } else if (Platform.isWindows) { + expect(windowsInfo.computerName, isNotNull); + expect(deviceInfo, same(windowsInfo)); + } else if (Platform.isLinux) { + expect(linuxInfo.name, isNotNull); + expect(deviceInfo, same(linuxInfo)); + } else if (Platform.isMacOS) { + expect(macosInfo.computerName, isNotNull); + expect(deviceInfo, same(macosInfo)); + } + } + }); + + testWidgets('Can get non-null iOS utsname fields', + (WidgetTester tester) async { + expect(iosInfo.utsname.machine, isNotNull); + expect(iosInfo.utsname.nodename, isNotNull); + expect(iosInfo.utsname.release, isNotNull); + expect(iosInfo.utsname.sysname, isNotNull); + expect(iosInfo.utsname.version, isNotNull); + }, skip: !Platform.isIOS); + + testWidgets('Check all android info values are available', + (WidgetTester tester) async { + if (androidInfo.version.sdkInt >= 23) { + expect(androidInfo.version.baseOS, isNotNull); + expect(androidInfo.version.previewSdkInt, isNotNull); + expect(androidInfo.version.securityPatch, isNotNull); + } + + expect(androidInfo.version.codename, isNotNull); + expect(androidInfo.version.incremental, isNotNull); + expect(androidInfo.version.release, isNotNull); + expect(androidInfo.version.sdkInt, isNotNull); + expect(androidInfo.board, isNotNull); + expect(androidInfo.bootloader, isNotNull); + expect(androidInfo.brand, isNotNull); + expect(androidInfo.device, isNotNull); + expect(androidInfo.display, isNotNull); + expect(androidInfo.fingerprint, isNotNull); + expect(androidInfo.hardware, isNotNull); + + expect(androidInfo.host, isNotNull); + expect(androidInfo.id, isNotNull); + expect(androidInfo.manufacturer, isNotNull); + expect(androidInfo.model, isNotNull); + expect(androidInfo.product, isNotNull); + expect(androidInfo.name, isNotNull); + + expect(androidInfo.supported32BitAbis, isNotNull); + expect(androidInfo.supported64BitAbis, isNotNull); + expect(androidInfo.supportedAbis, isNotNull); + + expect(androidInfo.tags, isNotNull); + expect(androidInfo.type, isNotNull); + expect(androidInfo.isPhysicalDevice, isNotNull); + expect(androidInfo.systemFeatures, isNotNull); + expect(androidInfo.serialNumber, isNotNull); + }, skip: !Platform.isAndroid); + + testWidgets('Check all macos info values are available', + ((WidgetTester tester) async { + expect(macosInfo.computerName, isNotNull); + expect(macosInfo.hostName, isNotNull); + expect(macosInfo.arch, isNotNull); + expect(macosInfo.model, isNotNull); + expect(macosInfo.modelName, isNotNull); + expect(macosInfo.kernelVersion, isNotNull); + expect(macosInfo.osRelease, isNotNull); + expect(macosInfo.activeCPUs, isNotNull); + expect(macosInfo.memorySize, isNotNull); + expect(macosInfo.cpuFrequency, isNotNull); + expect(macosInfo.systemGUID, isNotNull); + }), skip: !Platform.isMacOS); + + testWidgets('Check all Linux info values are available', + ((WidgetTester tester) async { + expect(linuxInfo.name, isNotNull); + expect(linuxInfo.version, isNotNull); + expect(linuxInfo.id, isNotNull); + expect(linuxInfo.idLike, isNotNull); + expect(linuxInfo.versionCodename, isNotNull); + expect(linuxInfo.versionId, isNotNull); + expect(linuxInfo.prettyName, isNotNull); + expect(linuxInfo.buildId, isNull); + expect(linuxInfo.variant, isNull); + expect(linuxInfo.variantId, isNull); + }), skip: !Platform.isLinux); + + testWidgets('Check all Windows info values are available', + ((WidgetTester tester) async { + expect( + windowsInfo.numberOfCores, + isPositive, + ); + expect( + windowsInfo.computerName, + isNotEmpty, + ); + expect( + windowsInfo.systemMemoryInMegabytes, + isPositive, + ); + expect( + windowsInfo.userName, + isNotEmpty, + ); + expect( + windowsInfo.majorVersion, + equals(10), + ); + expect( + windowsInfo.minorVersion, + equals(0), + ); + expect( + windowsInfo.buildNumber, + greaterThan(10240), + ); + expect( + windowsInfo.platformId, + equals(2), + ); + expect( + windowsInfo.reserved, + isZero, + ); + expect( + windowsInfo.buildLab, + isNotEmpty, + ); + expect( + windowsInfo.buildLab, + startsWith( + windowsInfo.buildNumber.toString(), + ), + ); + expect( + windowsInfo.buildLabEx, + isNotEmpty, + ); + expect( + windowsInfo.buildLab, + startsWith(windowsInfo.buildNumber.toString()), + ); + expect( + windowsInfo.digitalProductId, + isNotEmpty, + ); + expect( + windowsInfo.editionId, + isNotEmpty, + ); + expect( + windowsInfo.productId, + isNotEmpty, + ); + expect( + RegExp(r'^([A-Z0-9]{5}-){4}[A-Z0-9]{5}$') + .hasMatch(windowsInfo.productId) || + RegExp(r'^([A-Z0-9]{5}-){3}[A-Z0-9]{5}$') + .hasMatch(windowsInfo.productId), + isTrue, + ); + expect( + windowsInfo.productName, + isNotEmpty, + ); + expect( + windowsInfo.productName, + startsWith('Windows'), + ); + expect( + windowsInfo.releaseId, + isNotEmpty, + ); + expect( + windowsInfo.deviceId, + isNotEmpty, + ); + }), skip: !Platform.isWindows); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100755 index 00000000..8c6e5614 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Debug.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Debug.xcconfig new file mode 100755 index 00000000..ec97fc6f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Release.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Release.xcconfig new file mode 100755 index 00000000..c4855bfe --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..075d8eec --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,723 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 429829504B428B91CD34394A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E34A4006F430DB1C5A018A69 /* Pods_Runner.framework */; }; + 5DA2260ADE5F76F3FFB815A0 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0CDBB1B1CAFCC61F3647887B /* Pods_RunnerTests.framework */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0CDBB1B1CAFCC61F3647887B /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 6FDE560C1C66BB7D507C271F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 70B46233CBC827D9357CAED6 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B3E39AFFADC3FF84A14CEAD9 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + B5226E28C7B6DFA3F85A5F86 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + CC560B6DE1FF1FA91F20AF89 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + E34A4006F430DB1C5A018A69 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F7BF1F60B00C1E3390715BB3 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 479820A9DCB23F89315408D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5DA2260ADE5F76F3FFB815A0 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 429829504B428B91CD34394A /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2A76172809353E74F0878C8F /* Frameworks */ = { + isa = PBXGroup; + children = ( + E34A4006F430DB1C5A018A69 /* Pods_Runner.framework */, + 0CDBB1B1CAFCC61F3647887B /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + EE25C9049E007CD6D24A97DF /* Pods */, + 2A76172809353E74F0878C8F /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + EE25C9049E007CD6D24A97DF /* Pods */ = { + isa = PBXGroup; + children = ( + 6FDE560C1C66BB7D507C271F /* Pods-Runner.debug.xcconfig */, + 70B46233CBC827D9357CAED6 /* Pods-Runner.release.xcconfig */, + B5226E28C7B6DFA3F85A5F86 /* Pods-Runner.profile.xcconfig */, + B3E39AFFADC3FF84A14CEAD9 /* Pods-RunnerTests.debug.xcconfig */, + CC560B6DE1FF1FA91F20AF89 /* Pods-RunnerTests.release.xcconfig */, + F7BF1F60B00C1E3390715BB3 /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + AC296610EEC611E8563F8C04 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + 479820A9DCB23F89315408D4 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + F83E525764739090E301A316 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 4FD9CA2815573411DDA641D3 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 4FD9CA2815573411DDA641D3 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + AC296610EEC611E8563F8C04 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + F83E525764739090E301A316 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = B3E39AFFADC3FF84A14CEAD9 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = CC560B6DE1FF1FA91F20AF89 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F7BF1F60B00C1E3390715BB3 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..919434a6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..8e3ca5df --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100755 index 00000000..f9b0d7c5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/AppDelegate.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/AppDelegate.swift new file mode 100755 index 00000000..b6363034 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..d36b1fab --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100755 index 00000000..dc9ada47 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100755 index 00000000..7353c41e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100755 index 00000000..6ed2d933 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100755 index 00000000..4cd7b009 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100755 index 00000000..fe730945 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100755 index 00000000..321773cd Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100755 index 00000000..797d452e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100755 index 00000000..502f463a Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100755 index 00000000..0ec30343 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100755 index 00000000..e9f5fea2 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100755 index 00000000..84ac32ae Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100755 index 00000000..8953cba0 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100755 index 00000000..0467bf12 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100755 index 00000000..0bedcf2f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100755 index 00000000..9da19eac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100755 index 00000000..89c2725b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100755 index 00000000..f2e259c7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/Main.storyboard b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100755 index 00000000..f3c28516 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Info.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Info.plist new file mode 100755 index 00000000..c30f9332 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Info.plist @@ -0,0 +1,51 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Device Info Plus + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + device_info_plus_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Runner-Bridging-Header.h b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Runner-Bridging-Header.h new file mode 100755 index 00000000..308a2a56 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/RunnerTests/RunnerTests.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..86a7c3b1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/lib/main.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/lib/main.dart new file mode 100755 index 00000000..24afdc09 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/lib/main.dart @@ -0,0 +1,269 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'dart:developer' as developer; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +void main() { + runZonedGuarded(() { + runApp(const MyApp()); + }, (dynamic error, dynamic stack) { + developer.log("Something went wrong!", error: error, stackTrace: stack); + }); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + static final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); + Map _deviceData = {}; + + @override + void initState() { + super.initState(); + initPlatformState(); + } + + Future initPlatformState() async { + var deviceData = {}; + + try { + if (kIsWeb) { + deviceData = _readWebBrowserInfo(await deviceInfoPlugin.webBrowserInfo); + } else { + deviceData = switch (defaultTargetPlatform) { + TargetPlatform.android => + _readAndroidBuildData(await deviceInfoPlugin.androidInfo), + TargetPlatform.iOS => + _readIosDeviceInfo(await deviceInfoPlugin.iosInfo), + TargetPlatform.linux => + _readLinuxDeviceInfo(await deviceInfoPlugin.linuxInfo), + TargetPlatform.windows => + _readWindowsDeviceInfo(await deviceInfoPlugin.windowsInfo), + TargetPlatform.macOS => + _readMacOsDeviceInfo(await deviceInfoPlugin.macOsInfo), + TargetPlatform.fuchsia => { + 'Error:': 'Fuchsia platform isn\'t supported' + }, + }; + } + } on PlatformException { + deviceData = { + 'Error:': 'Failed to get platform version.' + }; + } + + if (!mounted) return; + + setState(() { + _deviceData = deviceData; + }); + } + + Map _readAndroidBuildData(AndroidDeviceInfo build) { + return { + 'version.securityPatch': build.version.securityPatch, + 'version.sdkInt': build.version.sdkInt, + 'version.release': build.version.release, + 'version.previewSdkInt': build.version.previewSdkInt, + 'version.incremental': build.version.incremental, + 'version.codename': build.version.codename, + 'version.baseOS': build.version.baseOS, + 'board': build.board, + 'bootloader': build.bootloader, + 'brand': build.brand, + 'device': build.device, + 'display': build.display, + 'fingerprint': build.fingerprint, + 'hardware': build.hardware, + 'host': build.host, + 'id': build.id, + 'manufacturer': build.manufacturer, + 'model': build.model, + 'product': build.product, + 'name': build.name, + 'supported32BitAbis': build.supported32BitAbis, + 'supported64BitAbis': build.supported64BitAbis, + 'supportedAbis': build.supportedAbis, + 'tags': build.tags, + 'type': build.type, + 'isPhysicalDevice': build.isPhysicalDevice, + 'systemFeatures': build.systemFeatures, + 'serialNumber': build.serialNumber, + 'isLowRamDevice': build.isLowRamDevice, + }; + } + + Map _readIosDeviceInfo(IosDeviceInfo data) { + return { + 'name': data.name, + 'systemName': data.systemName, + 'systemVersion': data.systemVersion, + 'model': data.model, + 'modelName': data.modelName, + 'localizedModel': data.localizedModel, + 'identifierForVendor': data.identifierForVendor, + 'isPhysicalDevice': data.isPhysicalDevice, + 'isiOSAppOnMac': data.isiOSAppOnMac, + 'utsname.sysname:': data.utsname.sysname, + 'utsname.nodename:': data.utsname.nodename, + 'utsname.release:': data.utsname.release, + 'utsname.version:': data.utsname.version, + 'utsname.machine:': data.utsname.machine, + }; + } + + Map _readLinuxDeviceInfo(LinuxDeviceInfo data) { + return { + 'name': data.name, + 'version': data.version, + 'id': data.id, + 'idLike': data.idLike, + 'versionCodename': data.versionCodename, + 'versionId': data.versionId, + 'prettyName': data.prettyName, + 'buildId': data.buildId, + 'variant': data.variant, + 'variantId': data.variantId, + 'machineId': data.machineId, + }; + } + + Map _readWebBrowserInfo(WebBrowserInfo data) { + return { + 'browserName': data.browserName.name, + 'appCodeName': data.appCodeName, + 'appName': data.appName, + 'appVersion': data.appVersion, + 'deviceMemory': data.deviceMemory, + 'language': data.language, + 'languages': data.languages, + 'platform': data.platform, + 'product': data.product, + 'productSub': data.productSub, + 'userAgent': data.userAgent, + 'vendor': data.vendor, + 'vendorSub': data.vendorSub, + 'hardwareConcurrency': data.hardwareConcurrency, + 'maxTouchPoints': data.maxTouchPoints, + }; + } + + Map _readMacOsDeviceInfo(MacOsDeviceInfo data) { + return { + 'computerName': data.computerName, + 'hostName': data.hostName, + 'arch': data.arch, + 'model': data.model, + 'modelName': data.modelName, + 'kernelVersion': data.kernelVersion, + 'majorVersion': data.majorVersion, + 'minorVersion': data.minorVersion, + 'patchVersion': data.patchVersion, + 'osRelease': data.osRelease, + 'activeCPUs': data.activeCPUs, + 'memorySize': data.memorySize, + 'cpuFrequency': data.cpuFrequency, + 'systemGUID': data.systemGUID, + }; + } + + Map _readWindowsDeviceInfo(WindowsDeviceInfo data) { + return { + 'numberOfCores': data.numberOfCores, + 'computerName': data.computerName, + 'systemMemoryInMegabytes': data.systemMemoryInMegabytes, + 'userName': data.userName, + 'majorVersion': data.majorVersion, + 'minorVersion': data.minorVersion, + 'buildNumber': data.buildNumber, + 'platformId': data.platformId, + 'csdVersion': data.csdVersion, + 'servicePackMajor': data.servicePackMajor, + 'servicePackMinor': data.servicePackMinor, + 'suitMask': data.suitMask, + 'productType': data.productType, + 'reserved': data.reserved, + 'buildLab': data.buildLab, + 'buildLabEx': data.buildLabEx, + 'digitalProductId': data.digitalProductId, + 'displayVersion': data.displayVersion, + 'editionId': data.editionId, + 'installDate': data.installDate, + 'productId': data.productId, + 'productName': data.productName, + 'registeredOwner': data.registeredOwner, + 'releaseId': data.releaseId, + 'deviceId': data.deviceId, + }; + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ThemeData( + useMaterial3: true, + colorSchemeSeed: const Color(0x9f4376f8), + ), + home: Scaffold( + appBar: AppBar( + title: Text(_getAppBarTitle()), + elevation: 4, + ), + body: ListView( + children: _deviceData.keys.map( + (String property) { + return Row( + children: [ + Container( + padding: const EdgeInsets.all(10), + child: Text( + property, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + ), + Expanded( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Text( + '${_deviceData[property]}', + maxLines: 10, + overflow: TextOverflow.ellipsis, + ), + ), + ), + ], + ); + }, + ).toList(), + ), + ), + ); + } + + String _getAppBarTitle() => kIsWeb + ? 'Web Browser info' + : switch (defaultTargetPlatform) { + TargetPlatform.android => 'Android Device Info', + TargetPlatform.iOS => 'iOS Device Info', + TargetPlatform.linux => 'Linux Device Info', + TargetPlatform.windows => 'Windows Device Info', + TargetPlatform.macOS => 'MacOS Device Info', + TargetPlatform.fuchsia => 'Fuchsia Device Info', + }; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/CMakeLists.txt new file mode 100755 index 00000000..fe30a3e6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "io.flutter.plugins.deviceinfoexample.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/flutter/CMakeLists.txt new file mode 100755 index 00000000..5b465c7e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/main.cc b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/main.cc new file mode 100755 index 00000000..8bc15615 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/main.cc @@ -0,0 +1,11 @@ +#include "my_application.h" + +int main(int argc, char **argv) { + // Only X11 is currently supported. + // Wayland support is being developed: + // https://github.com/flutter/flutter/issues/57932. + gdk_set_allowed_backends("x11"); + + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.cc b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.cc new file mode 100755 index 00000000..cef2f771 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.cc @@ -0,0 +1,45 @@ +#include "my_application.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication *application) { + GtkWindow *window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + + FlView *view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +static void my_application_class_init(MyApplicationClass *klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; +} + +static void my_application_init(MyApplication *self) {} + +MyApplication *my_application_new() { + return MY_APPLICATION(g_object_new( + my_application_get_type(), "application-id", APPLICATION_ID, nullptr)); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.h b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.h new file mode 100755 index 00000000..3258a73c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication *my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Debug.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100755 index 00000000..4b81f9b2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Release.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100755 index 00000000..5caa9d15 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100755 index 00000000..17738f85 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,791 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 1330411FFFFCBD68C52506B9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F374CDA27EFCEFF13CF00643 /* Pods_Runner.framework */; }; + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + B32C194861AFDC5B38D41D89 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F061CD8A37C585748E94D972 /* Pods_RunnerTests.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 279B31026D7637D54DF99D75 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* example_device_info.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example_device_info.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 7D5FF3AEF35298EDF0C1201D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + D768A5BD5BCBEE43226A64A7 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + D94DF7FF96C592E0D5C3E009 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + E07B0AE1E178661F8653244B /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + E92B0E6DF286F1A21B388CA1 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + F061CD8A37C585748E94D972 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F374CDA27EFCEFF13CF00643 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B32C194861AFDC5B38D41D89 /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1330411FFFFCBD68C52506B9 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + C28D557964D09D46EC4A0164 /* Pods */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* example_device_info.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + C28D557964D09D46EC4A0164 /* Pods */ = { + isa = PBXGroup; + children = ( + E07B0AE1E178661F8653244B /* Pods-Runner.debug.xcconfig */, + 7D5FF3AEF35298EDF0C1201D /* Pods-Runner.release.xcconfig */, + D768A5BD5BCBEE43226A64A7 /* Pods-Runner.profile.xcconfig */, + D94DF7FF96C592E0D5C3E009 /* Pods-RunnerTests.debug.xcconfig */, + E92B0E6DF286F1A21B388CA1 /* Pods-RunnerTests.release.xcconfig */, + 279B31026D7637D54DF99D75 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + F374CDA27EFCEFF13CF00643 /* Pods_Runner.framework */, + F061CD8A37C585748E94D972 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 55412E34F2958028872E9D98 /* [CP] Check Pods Manifest.lock */, + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 88B27E32653C92A6BA8EB23C /* [CP] Check Pods Manifest.lock */, + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + 5BEC5C74096CA740BAE5D11D /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* example_device_info.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; + 55412E34F2958028872E9D98 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 5BEC5C74096CA740BAE5D11D /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 88B27E32653C92A6BA8EB23C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D94DF7FF96C592E0D5C3E009 /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example_device_info.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example_device_info"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E92B0E6DF286F1A21B388CA1 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example_device_info.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example_device_info"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 279B31026D7637D54DF99D75 /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.exampleDeviceInfo.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example_device_info.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/example_device_info"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100755 index 00000000..7bb1c7df --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100755 index 00000000..21a3cc14 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100755 index 00000000..18d98100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/AppDelegate.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/AppDelegate.swift new file mode 100755 index 00000000..8e02df28 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 00000000..a2ec33f1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "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" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100755 index 00000000..82b6f9d9 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100755 index 00000000..13b35eba Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100755 index 00000000..0a3f5fa4 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100755 index 00000000..bdb57226 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100755 index 00000000..f083318e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100755 index 00000000..326c0e72 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100755 index 00000000..2f1632cf Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Base.lproj/MainMenu.xib b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Base.lproj/MainMenu.xib new file mode 100755 index 00000000..80e867a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/AppInfo.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100755 index 00000000..af912343 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = device_info_plus_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = io.flutter.plugins.deviceinfoexample.example + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2023 io.flutter.plugins.deviceinfoexample. All rights reserved. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Debug.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Debug.xcconfig new file mode 100755 index 00000000..36b0fd94 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Release.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Release.xcconfig new file mode 100755 index 00000000..dff4f495 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Warnings.xcconfig b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100755 index 00000000..42bcbf47 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/DebugProfile.entitlements b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/DebugProfile.entitlements new file mode 100755 index 00000000..dddb8a30 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Info.plist b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Info.plist new file mode 100755 index 00000000..4789daa6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/MainFlutterWindow.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/MainFlutterWindow.swift new file mode 100755 index 00000000..3cc05eb2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Release.entitlements b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Release.entitlements new file mode 100755 index 00000000..852fa1a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/RunnerTests/RunnerTests.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/RunnerTests/RunnerTests.swift new file mode 100755 index 00000000..5418c9f5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/pubspec.yaml new file mode 100755 index 00000000..8d8200cf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/pubspec.yaml @@ -0,0 +1,25 @@ +name: device_info_plus_example +description: Demonstrates how to use the device_info_plus plugin. + +dependencies: + flutter: + sdk: flutter + device_info_plus: ^11.3.0 + +dev_dependencies: + flutter_driver: + sdk: flutter + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + flutter_lints: ">=4.0.0 <6.0.0" + +flutter: + uses-material-design: true + +environment: + sdk: '>=3.4.0 <4.0.0' + flutter: '>=3.22.0' + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/favicon.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/favicon.png new file mode 100755 index 00000000..8aaa46ac Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/favicon.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-192.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-192.png new file mode 100755 index 00000000..b749bfef Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-192.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-512.png b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-512.png new file mode 100755 index 00000000..88cfd48d Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/icons/Icon-512.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/index.html b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/index.html new file mode 100755 index 00000000..99eacb28 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/index.html @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + example + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/manifest.json b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/manifest.json new file mode 100755 index 00000000..8c012917 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/CMakeLists.txt new file mode 100755 index 00000000..abf90408 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.15) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..b02c5485 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..977e38b5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/Runner.rc b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/Runner.rc new file mode 100755 index 00000000..13f98c0a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "io.flutter.plugins.deviceinfoexample" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 io.flutter.plugins.deviceinfoexample. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..0f0105d9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.cpp @@ -0,0 +1,64 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opporutunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..69234d4f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/flutter_window.h @@ -0,0 +1,39 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "run_loop.h" +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { +public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop *run_loop, + const flutter::DartProject &project); + virtual ~FlutterWindow(); + +protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + +private: + // The run loop driving events for this window. + RunLoop *run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/main.cpp new file mode 100755 index 00000000..09895686 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/main.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resource.h b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resources/app_icon.ico b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/resources/app_icon.ico differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.cpp new file mode 100755 index 00000000..31b89f62 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.cpp @@ -0,0 +1,66 @@ +#include "run_loop.h" + +#include + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterEngine *flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto instance : flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.h b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.h new file mode 100755 index 00000000..7fe1aacc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/run_loop.h @@ -0,0 +1,38 @@ +#ifndef RUNNER_RUN_LOOP_H_ +#define RUNNER_RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { +public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const &) = delete; + RunLoop &operator=(RunLoop const &) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine *flutter_instance); + +private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUNNER_RUN_LOOP_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/runner.exe.manifest b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.cpp new file mode 100755 index 00000000..7758aabf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.cpp @@ -0,0 +1,63 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t **argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t *utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.h new file mode 100755 index 00000000..ff43ce2c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t *utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..90ff01e5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.cpp @@ -0,0 +1,237 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { +public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar *GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t *GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + +private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar *instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar *WindowClassRegistrar::instance_ = nullptr; + +const wchar_t *WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size) { + Destroy(); + + const wchar_t *window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window *that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window *Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.h new file mode 100755 index 00000000..7b518125 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/example/windows/runner/win32_window.h @@ -0,0 +1,95 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { +public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring &title, const Point &origin, + const Size &size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + +protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + +private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window *GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus.podspec b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus.podspec new file mode 100755 index 00000000..6038dd29 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus.podspec @@ -0,0 +1,24 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'device_info_plus' + s.version = '0.0.1' + s.summary = 'Flutter Device Info Plus' + s.description = <<-DESC +Get current device information from within the Flutter application. +Downloaded by pub (not CocoaPods). + DESC + s.homepage = 'https://github.com/fluttercommunity/plus_plugins' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Community Team' => 'authors@fluttercommunity.dev' } + s.source = { :http => 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/device_info_plus' } + s.documentation_url = 'https://pub.dev/packages/device_info_plus' + s.source_files = 'device_info_plus/Sources/device_info_plus/**/*.{h,m}' + s.public_header_files = 'device_info_plus/Sources/device_info_plus/include/**/*.h' + s.dependency 'Flutter' + s.platform = :ios, '12.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.resource_bundles = {'device_info_plus_privacy' => ['device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy']} +end + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Package.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Package.swift new file mode 100755 index 00000000..a4defdd7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "device_info_plus", + platforms: [ + .iOS("12.0"), + ], + products: [ + .library(name: "device-info-plus", targets: ["device_info_plus"]) + ], + dependencies: [], + targets: [ + .target( + name: "device_info_plus", + dependencies: [], + resources: [ + .process("PrivacyInfo.xcprivacy"), + ], + cSettings: [ + .headerSearchPath("include/device_info_plus") + ] + ) + ] +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m new file mode 100755 index 00000000..cda41d95 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.m @@ -0,0 +1,208 @@ +// +// DeviceIdentifiers.m +// device_info_plus +// +// Created by Volodymyr on 06.11.2024. +// +#import "./include/device_info_plus/DeviceIdentifiers.h" + +@implementation DeviceIdentifiers + ++ (NSString *)userKnownDeviceModel:(NSString *)identifier { + if ([identifier isEqualToString:@"iPhone6,1"]) { + return @"iPhone 5s"; + } else if ([identifier isEqualToString:@"iPhone6,2"]) { + return @"iPhone 5s"; + } else if ([identifier isEqualToString:@"iPhone7,2"]) { + return @"iPhone 6"; + } else if ([identifier isEqualToString:@"iPhone7,1"]) { + return @"iPhone 6 Plus"; + } else if ([identifier isEqualToString:@"iPhone8,1"]) { + return @"iPhone 6s"; + } else if ([identifier isEqualToString:@"iPhone8,2"]) { + return @"iPhone 6s Plus"; + } else if ([identifier isEqualToString:@"iPhone9,1"] || + [identifier isEqualToString:@"iPhone9,3"]) { + return @"iPhone 7"; + } else if ([identifier isEqualToString:@"iPhone9,2"] || + [identifier isEqualToString:@"iPhone9,4"]) { + return @"iPhone 7 Plus"; + } else if ([identifier isEqualToString:@"iPhone8,4"]) { + return @"iPhone SE"; + } else if ([identifier isEqualToString:@"iPhone10,1"] || + [identifier isEqualToString:@"iPhone10,4"]) { + return @"iPhone 8"; + } else if ([identifier isEqualToString:@"iPhone10,2"] || + [identifier isEqualToString:@"iPhone10,5"]) { + return @"iPhone 8 Plus"; + } else if ([identifier isEqualToString:@"iPhone10,3"] || + [identifier isEqualToString:@"iPhone10,6"]) { + return @"iPhone X"; + } else if ([identifier isEqualToString:@"iPhone11,2"]) { + return @"iPhone XS"; + } else if ([identifier isEqualToString:@"iPhone11,4"] || + [identifier isEqualToString:@"iPhone11,6"]) { + return @"iPhone XS Max"; + } else if ([identifier isEqualToString:@"iPhone11,8"]) { + return @"iPhone XR"; + } else if ([identifier isEqualToString:@"iPhone12,1"]) { + return @"iPhone 11"; + } else if ([identifier isEqualToString:@"iPhone12,3"]) { + return @"iPhone 11 Pro"; + } else if ([identifier isEqualToString:@"iPhone12,5"]) { + return @"iPhone 11 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone12,8"]) { + return @"iPhone SE 2"; + } else if ([identifier isEqualToString:@"iPhone13,2"]) { + return @"iPhone 12"; + } else if ([identifier isEqualToString:@"iPhone13,1"]) { + return @"iPhone 12 Mini"; + } else if ([identifier isEqualToString:@"iPhone13,3"]) { + return @"iPhone 12 Pro"; + } else if ([identifier isEqualToString:@"iPhone13,4"]) { + return @"iPhone 12 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone14,5"]) { + return @"iPhone 13"; + } else if ([identifier isEqualToString:@"iPhone14,4"]) { + return @"iPhone 13 Mini"; + } else if ([identifier isEqualToString:@"iPhone14,2"]) { + return @"iPhone 13 Pro"; + } else if ([identifier isEqualToString:@"iPhone14,3"]) { + return @"iPhone 13 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone14,6"]) { + return @"iPhone SE 3"; + } else if ([identifier isEqualToString:@"iPhone14,7"]) { + return @"iPhone 14"; + } else if ([identifier isEqualToString:@"iPhone14,8"]) { + return @"iPhone 14 Plus"; + } else if ([identifier isEqualToString:@"iPhone15,2"]) { + return @"iPhone 14 Pro"; + } else if ([identifier isEqualToString:@"iPhone15,3"]) { + return @"iPhone 14 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone15,4"]) { + return @"iPhone 15"; + } else if ([identifier isEqualToString:@"iPhone15,5"]) { + return @"iPhone 15 Plus"; + } else if ([identifier isEqualToString:@"iPhone16,1"]) { + return @"iPhone 15 Pro"; + } else if ([identifier isEqualToString:@"iPhone16,2"]) { + return @"iPhone 15 Pro Max"; + } else if ([identifier isEqualToString:@"iPhone17,3"]) { + return @"iPhone 16"; + } else if ([identifier isEqualToString:@"iPhone17,4"]) { + return @"iPhone 16 Plus"; + } else if ([identifier isEqualToString:@"iPhone17,1"]) { + return @"iPhone 16 Pro"; + } else if ([identifier isEqualToString:@"iPhone17,2"]) { + return @"iPhone 16 Pro Max"; + // iPads + } else if ([identifier isEqualToString:@"iPad4,1"] || + [identifier isEqualToString:@"iPad4,2"] || + [identifier isEqualToString:@"iPad4,3"]) { + return @"iPad Air"; + } else if ([identifier isEqualToString:@"iPad5,3"] || + [identifier isEqualToString:@"iPad5,4"]) { + return @"iPad Air 2"; + } else if ([identifier isEqualToString:@"iPad6,11"] || + [identifier isEqualToString:@"iPad6,12"]) { + return @"iPad 5"; + } else if ([identifier isEqualToString:@"iPad7,5"] || + [identifier isEqualToString:@"iPad7,6"]) { + return @"iPad 6"; + } else if ([identifier isEqualToString:@"iPad11,3"] || + [identifier isEqualToString:@"iPad11,4"]) { + return @"iPad Air 3"; + } else if ([identifier isEqualToString:@"iPad7,11"] || + [identifier isEqualToString:@"iPad7,12"]) { + return @"iPad 7"; + } else if ([identifier isEqualToString:@"iPad11,6"] || + [identifier isEqualToString:@"iPad11,7"]) { + return @"iPad 8"; + } else if ([identifier isEqualToString:@"iPad12,1"] || + [identifier isEqualToString:@"iPad12,2"]) { + return @"iPad 9"; + } else if ([identifier isEqualToString:@"iPad13,18"] || + [identifier isEqualToString:@"iPad13,19"]) { + return @"iPad 10"; + } else if ([identifier isEqualToString:@"iPad13,1"] || + [identifier isEqualToString:@"iPad13,2"]) { + return @"iPad Air 4"; + } else if ([identifier isEqualToString:@"iPad13,16"] || + [identifier isEqualToString:@"iPad13,17"]) { + return @"iPad Air 5"; + } else if ([identifier isEqualToString:@"iPad14,8"] || + [identifier isEqualToString:@"iPad14,9"]) { + return @"iPad Air 11-Inch M2"; + } else if ([identifier isEqualToString:@"iPad14,10"] || + [identifier isEqualToString:@"iPad14,11"]) { + return @"iPad Air 13-Inch M2"; + } else if ([identifier isEqualToString:@"iPad2,5"] || + [identifier isEqualToString:@"iPad2,6"] || + [identifier isEqualToString:@"iPad2,7"]) { + return @"iPad Mini"; + } else if ([identifier isEqualToString:@"iPad4,4"] || + [identifier isEqualToString:@"iPad4,5"] || + [identifier isEqualToString:@"iPad4,6"]) { + return @"iPad Mini 2"; + } else if ([identifier isEqualToString:@"iPad4,7"] || + [identifier isEqualToString:@"iPad4,8"] || + [identifier isEqualToString:@"iPad4,9"]) { + return @"iPad Mini 3"; + } else if ([identifier isEqualToString:@"iPad5,1"] || + [identifier isEqualToString:@"iPad5,2"]) { + return @"iPad Mini 4"; + } else if ([identifier isEqualToString:@"iPad11,1"] || + [identifier isEqualToString:@"iPad11,2"]) { + return @"iPad Mini 5"; + } else if ([identifier isEqualToString:@"iPad14,1"] || + [identifier isEqualToString:@"iPad14,2"]) { + return @"iPad Mini 6"; + } else if ([identifier isEqualToString:@"iPad6,3"] || + [identifier isEqualToString:@"iPad6,4"]) { + return @"iPad Pro 9-Inch"; + } else if ([identifier isEqualToString:@"iPad6,7"] || + [identifier isEqualToString:@"iPad6,8"]) { + return @"iPad Pro 12-Inch"; + } else if ([identifier isEqualToString:@"iPad7,1"] || [identifier isEqualToString:@"iPad7,2"]) { + return @"iPad Pro 12-Inch 2"; + } else if ([identifier isEqualToString:@"iPad7,3"] || [identifier isEqualToString:@"iPad7,4"]) { + return @"iPad Pro 10-Inch"; + } else if ([identifier isEqualToString:@"iPad8,1"] || [identifier isEqualToString:@"iPad8,2"] || + [identifier isEqualToString:@"iPad8,3"] || [identifier isEqualToString:@"iPad8,4"]) { + return @"iPad Pro 11-Inch"; + } else if ([identifier isEqualToString:@"iPad8,5"] || [identifier isEqualToString:@"iPad8,6"] || + [identifier isEqualToString:@"iPad8,7"] || [identifier isEqualToString:@"iPad8,8"]) { + return @"iPad Pro 12-Inch 3"; + } else if ([identifier isEqualToString:@"iPad8,9"] || + [identifier isEqualToString:@"iPad8,10"]) { + return @"iPad Pro 11-Inch 2"; + } else if ([identifier isEqualToString:@"iPad8,11"] || + [identifier isEqualToString:@"iPad8,12"]) { + return @"iPad Pro 12-Inch 4"; + } else if ([identifier isEqualToString:@"iPad13,4"] || + [identifier isEqualToString:@"iPad13,5"] || + [identifier isEqualToString:@"iPad13,6"] || + [identifier isEqualToString:@"iPad13,7"]) { + return @"iPad Pro 11-Inch 3"; + } else if ([identifier isEqualToString:@"iPad13,8"] || + [identifier isEqualToString:@"iPad13,9"] || + [identifier isEqualToString:@"iPad13,10"] || + [identifier isEqualToString:@"iPad13,11"]) { + return @"iPad Pro 12-Inch 5"; + } else if ([identifier isEqualToString:@"iPad14,3"] || + [identifier isEqualToString:@"iPad14,4"]) { + return @"iPad Pro 11-Inch 4"; + } else if ([identifier isEqualToString:@"iPad14,5"] || + [identifier isEqualToString:@"iPad14,6"]) { + return @"iPad Pro 12-Inch 6"; + } else if ([identifier isEqualToString:@"iPad16,3"] || + [identifier isEqualToString:@"iPad16,4"]) { + return @"iPad Pro 11-Inch (M4)"; + } else if ([identifier isEqualToString:@"iPad16,5"] || + [identifier isEqualToString:@"iPad16,6"]) { + return @"iPad Pro 13-Inch (M4)"; + } else { + return @"Unknown device"; + } +} +@end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m new file mode 100755 index 00000000..2b495c7c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/FPPDeviceInfoPlusPlugin.m @@ -0,0 +1,77 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "./include/device_info_plus/FPPDeviceInfoPlusPlugin.h" +#import "./include/device_info_plus/DeviceIdentifiers.h" +#import + +@implementation FPPDeviceInfoPlusPlugin ++ (void)registerWithRegistrar:(NSObject *)registrar { + FlutterMethodChannel *channel = [FlutterMethodChannel + methodChannelWithName:@"dev.fluttercommunity.plus/device_info" + binaryMessenger:[registrar messenger]]; + FPPDeviceInfoPlusPlugin *instance = [[FPPDeviceInfoPlusPlugin alloc] init]; + [registrar addMethodCallDelegate:instance channel:channel]; +} + +- (void)handleMethodCall:(FlutterMethodCall *)call + result:(FlutterResult)result { + if ([@"getDeviceInfo" isEqualToString:call.method]) { + UIDevice *device = [UIDevice currentDevice]; + struct utsname un; + uname(&un); + + NSNumber *isPhysicalNumber = + [NSNumber numberWithBool:[self isDevicePhysical]]; + NSProcessInfo *info = [NSProcessInfo processInfo]; + NSNumber *isiOSAppOnMac = [NSNumber numberWithBool:NO]; + if (@available(iOS 14.0, *)) { + isiOSAppOnMac = [NSNumber numberWithBool:[info isiOSAppOnMac]]; + } + NSString *machine; + NSString *deviceName; + if ([self isDevicePhysical]) { + machine = @(un.machine); + } else { + machine = [info environment][@"SIMULATOR_MODEL_IDENTIFIER"]; + } + deviceName = [DeviceIdentifiers userKnownDeviceModel:machine]; + + result(@{ + @"name" : [device name], + @"systemName" : [device systemName], + @"systemVersion" : [device systemVersion], + @"model" : [device model], + @"localizedModel" : [device localizedModel], + @"modelName" : deviceName, + @"identifierForVendor" : [[device identifierForVendor] UUIDString] + ?: [NSNull null], + @"isPhysicalDevice" : isPhysicalNumber, + @"isiOSAppOnMac" : isiOSAppOnMac, + @"utsname" : @{ + @"sysname" : @(un.sysname), + @"nodename" : @(un.nodename), + @"release" : @(un.release), + @"version" : @(un.version), + @"machine" : machine, + } + }); + } else { + result(FlutterMethodNotImplemented); + } +} + +// return value is false if code is run on a simulator +- (BOOL)isDevicePhysical { + BOOL isPhysicalDevice = NO; +#if TARGET_OS_SIMULATOR + isPhysicalDevice = NO; +#else + isPhysicalDevice = YES; +#endif + + return isPhysicalDevice; +} + +@end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy new file mode 100755 index 00000000..a34b7e2e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/DeviceIdentifiers.h b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/DeviceIdentifiers.h new file mode 100755 index 00000000..0f5c8d70 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/DeviceIdentifiers.h @@ -0,0 +1,13 @@ +// +// DeviceIdentifiers.h +// device_info_plus +// +// Created by Volodymyr on 06.11.2024. +// +#import + +@interface DeviceIdentifiers : NSObject + ++ (NSString *)userKnownDeviceModel:(NSString *)identifier; + +@end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/FPPDeviceInfoPlusPlugin.h b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/FPPDeviceInfoPlusPlugin.h new file mode 100755 index 00000000..430e81ce --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/ios/device_info_plus/Sources/device_info_plus/include/device_info_plus/FPPDeviceInfoPlusPlugin.h @@ -0,0 +1,8 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +@interface FPPDeviceInfoPlusPlugin : NSObject +@end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/device_info_plus.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/device_info_plus.dart new file mode 100755 index 00000000..38c83762 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/device_info_plus.dart @@ -0,0 +1,115 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:io'; + +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:flutter/foundation.dart'; + +import 'src/model/android_device_info.dart'; +import 'src/model/ios_device_info.dart'; +import 'src/model/linux_device_info.dart'; +import 'src/model/macos_device_info.dart'; +import 'src/model/web_browser_info.dart'; +import 'src/model/windows_device_info.dart'; + +export 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart' + show BaseDeviceInfo; + +export 'src/model/android_device_info.dart'; +export 'src/model/ios_device_info.dart'; +export 'src/model/linux_device_info.dart'; +export 'src/model/macos_device_info.dart'; +export 'src/model/web_browser_info.dart'; +export 'src/model/windows_device_info.dart'; + +export 'src/device_info_plus_linux.dart' + if (dart.library.js_interop) 'src/device_info_plus_web.dart'; +export 'src/device_info_plus_windows.dart' + if (dart.library.js_interop) 'src/device_info_plus_web.dart'; + +/// Provides device and operating system information. +class DeviceInfoPlugin { + /// No work is done when instantiating the plugin. It's safe to call this + /// repeatedly or in performance-sensitive blocks. + DeviceInfoPlugin(); + + // This is to manually endorse the Linux plugin until automatic registration + // of dart plugins is implemented. + // See https://github.com/flutter/flutter/issues/52267 for more details. + static DeviceInfoPlatform get _platform { + return DeviceInfoPlatform.instance; + } + + /// This information does not change from call to call. Cache it. + AndroidDeviceInfo? _cachedAndroidDeviceInfo; + + /// Information derived from `android.os.Build`. + /// + /// See: https://developer.android.com/reference/android/os/Build.html + Future get androidInfo async => + _cachedAndroidDeviceInfo ??= + AndroidDeviceInfo.fromMap((await _platform.deviceInfo()).data); + + /// This information does not change from call to call. Cache it. + IosDeviceInfo? _cachedIosDeviceInfo; + + /// Information derived from `UIDevice`. + /// + /// See: https://developer.apple.com/documentation/uikit/uidevice + Future get iosInfo async => _cachedIosDeviceInfo ??= + IosDeviceInfo.fromMap((await _platform.deviceInfo()).data); + + /// This information does not change from call to call. Cache it. + LinuxDeviceInfo? _cachedLinuxDeviceInfo; + + /// Information derived from `/etc/os-release`. + /// + /// See: https://www.freedesktop.org/software/systemd/man/os-release.html + Future get linuxInfo async => _cachedLinuxDeviceInfo ??= + await _platform.deviceInfo() as LinuxDeviceInfo; + + /// This information does not change from call to call. Cache it. + WebBrowserInfo? _cachedWebBrowserInfo; + + /// Information derived from `Navigator`. + Future get webBrowserInfo async => + _cachedWebBrowserInfo ??= await _platform.deviceInfo() as WebBrowserInfo; + + /// This information does not change from call to call. Cache it. + MacOsDeviceInfo? _cachedMacosDeviceInfo; + + /// Returns device information for macos. Information sourced from Sysctl. + Future get macOsInfo async => _cachedMacosDeviceInfo ??= + MacOsDeviceInfo.fromMap((await _platform.deviceInfo()).data); + + WindowsDeviceInfo? _cachedWindowsDeviceInfo; + + /// Returns device information for Windows. + Future get windowsInfo async => + _cachedWindowsDeviceInfo ??= + await _platform.deviceInfo() as WindowsDeviceInfo; + + /// Returns device information for the current platform. + Future get deviceInfo async { + if (kIsWeb) { + return webBrowserInfo; + } else { + if (Platform.isAndroid) { + return androidInfo; + } else if (Platform.isIOS) { + return iosInfo; + } else if (Platform.isLinux) { + return linuxInfo; + } else if (Platform.isMacOS) { + return macOsInfo; + } else if (Platform.isWindows) { + return windowsInfo; + } + } + // allow for extension of the plugin + return _platform.deviceInfo(); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_linux.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_linux.dart new file mode 100755 index 00000000..95ab8eac --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_linux.dart @@ -0,0 +1,104 @@ +import 'dart:async'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:file/file.dart'; +import 'package:file/local.dart'; +import 'package:meta/meta.dart'; + +/// See [DeviceInfoPlatform] +class DeviceInfoPlusLinuxPlugin extends DeviceInfoPlatform { + /// Register this dart class as the platform implementation for linux + static void registerWith() { + DeviceInfoPlatform.instance = DeviceInfoPlusLinuxPlugin(); + } + + LinuxDeviceInfo? _cache; + final FileSystem _fileSystem; + + /// + DeviceInfoPlusLinuxPlugin({@visibleForTesting FileSystem? fileSystem}) + : _fileSystem = fileSystem ?? const LocalFileSystem(); + + @override + Future deviceInfo() async { + return _cache ??= await _getInfo(); + } + + Future linuxInfo() async { + return (await deviceInfo()) as LinuxDeviceInfo; + } + + Future _getInfo() async { + final os = await _getOsRelease() ?? {}; + final lsb = await _getLsbRelease() ?? {}; + final machineId = await _getMachineId(); + + return LinuxDeviceInfo( + name: os['NAME'] ?? 'Linux', + version: os['VERSION'] ?? lsb['LSB_VERSION'], + id: os['ID'] ?? lsb['DISTRIB_ID'] ?? 'linux', + idLike: os['ID_LIKE']?.split(' '), + versionCodename: os['VERSION_CODENAME'] ?? lsb['DISTRIB_CODENAME'], + versionId: os['VERSION_ID'] ?? lsb['DISTRIB_RELEASE'], + prettyName: os['PRETTY_NAME'] ?? lsb['DISTRIB_DESCRIPTION'] ?? 'Linux', + buildId: os['BUILD_ID'], + variant: os['VARIANT'], + variantId: os['VARIANT_ID'], + machineId: machineId, + ); + } + + Future?> _getOsRelease() { + return _tryReadKeyValues('/etc/os-release').then((value) async => + value ?? await _tryReadKeyValues('/usr/lib/os-release')); + } + + Future?> _getLsbRelease() { + return _tryReadKeyValues('/etc/lsb-release'); + } + + Future _getMachineId() { + return _tryReadValue('/etc/machine-id'); + } + + Future _tryReadValue(String path) { + return _fileSystem + .file(path) + .readAsString() + .then((str) => str.trim(), onError: (_) => null); + } + + Future?> _tryReadKeyValues(String path) { + return _fileSystem + .file(path) + .readAsLines() + .then((lines) => lines.toKeyValues(), onError: (_) => null); + } +} + +extension _Unquote on String { + String removePrefix(String prefix) { + if (!startsWith(prefix)) return this; + return substring(prefix.length); + } + + String removeSuffix(String suffix) { + if (!endsWith(suffix)) return this; + return substring(0, length - suffix.length); + } + + String unquote() { + return removePrefix('"').removeSuffix('"'); + } +} + +extension _KeyValues on List { + Map toKeyValues() { + return Map.fromEntries(map((line) { + final parts = line.split('='); + if (parts.length != 2) return MapEntry(line, null); + return MapEntry(parts.first, parts.last.unquote()); + })); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_macos.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_macos.dart new file mode 100755 index 00000000..39e7bb81 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_macos.dart @@ -0,0 +1,2 @@ +// ignore: dangling_library_doc_comments +/// The platform interface handles the method channel calls. This file exists to silence errors on pub. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_web.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_web.dart new file mode 100755 index 00000000..30f5727c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_web.dart @@ -0,0 +1,60 @@ +import 'dart:async'; +import 'dart:js_interop'; +import 'package:web/web.dart' as html show window, Navigator; + +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +import 'model/web_browser_info.dart'; + +/// The web implementation of the BatteryPlusPlatform of the BatteryPlus plugin. +class DeviceInfoPlusWebPlugin extends DeviceInfoPlatform { + /// Constructs a DeviceInfoPlusPlugin. + DeviceInfoPlusWebPlugin(navigator) : _navigator = navigator; + + final html.Navigator _navigator; + + /// Factory method that initializes the DeviceInfoPlus plugin platform + /// with an instance of the plugin for the web. + static void registerWith(Registrar registrar) { + DeviceInfoPlatform.instance = + DeviceInfoPlusWebPlugin(html.window.navigator); + } + + @override + Future deviceInfo() { + return Future.value( + WebBrowserInfo.fromMap( + { + 'appCodeName': _navigator.appCodeName, + 'appName': _navigator.appName, + 'appVersion': _navigator.appVersion, + 'deviceMemory': _navigator.safeDeviceMemory, + 'language': _navigator.language, + 'languages': _navigator.languages.toDart, + 'platform': _navigator.platform, + 'product': _navigator.product, + 'productSub': _navigator.productSub, + 'userAgent': _navigator.userAgent, + 'vendor': _navigator.vendor, + 'vendorSub': _navigator.vendorSub, + 'hardwareConcurrency': _navigator.hardwareConcurrency, + 'maxTouchPoints': _navigator.maxTouchPoints, + }, + ), + ); + } +} + +/// Some Navigator properties are not fully supported in all browsers. +/// However, package:web does not provide a safe way to access these properties, +/// and assumes they are always not null. +/// +/// This extension provides a safe way to access these properties. +/// +/// See: https://github.com/dart-lang/web/issues/326 +/// https://github.com/fluttercommunity/plus_plugins/issues/3391 +extension SafeNavigationGetterExtensions on html.Navigator { + @JS('deviceMemory') + external double? get safeDeviceMemory; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_windows.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_windows.dart new file mode 100755 index 00000000..213a0b8f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/device_info_plus_windows.dart @@ -0,0 +1,180 @@ +/// The Windows implementation of `device_info_plus`. +library device_info_plus_windows; + +import 'dart:ffi'; +import 'dart:typed_data'; +import 'dart:developer' as developer; + +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:ffi/ffi.dart'; +import 'package:meta/meta.dart'; +import 'package:win32/win32.dart'; +import 'package:win32_registry/win32_registry.dart'; + +import 'model/windows_device_info.dart'; + +/// The Windows implementation of [DeviceInfoPlatform]. +class DeviceInfoPlusWindowsPlugin extends DeviceInfoPlatform { + /// Register this dart class as the platform implementation for windows + static void registerWith() { + DeviceInfoPlatform.instance = DeviceInfoPlusWindowsPlugin(); + } + + WindowsDeviceInfo? _cache; + + // In a well-meaning but somewhat misguided attempt to reduce apps from using + // version numbers for feature detection, most version number APIs don't give + // expected results on Windows 8 and above. RtlGetVersion is reliable and + // stable, but as a kernel API is documented in the Windows DDK (Driver + // Development Kit), rather than the SDK. As such, it's not included in + // package:win32, so we have to manually define it here. + // + // ignore: non_constant_identifier_names + void Function(Pointer) RtlGetVersion = + DynamicLibrary.open('ntdll.dll').lookupFunction< + Void Function(Pointer), + void Function(Pointer)>('RtlGetVersion'); + + /// Returns a [WindowsDeviceInfo] with information about the device. + @override + Future deviceInfo() { + return Future.value(_cache ??= getInfo()); + } + + @visibleForTesting + WindowsDeviceInfo getInfo() { + final systemInfo = calloc(); + final osVersionInfo = calloc() + ..ref.dwOSVersionInfoSize = sizeOf(); + + try { + final currentVersionKey = Registry.openPath(RegistryHive.localMachine, + path: r'SOFTWARE\Microsoft\Windows NT\CurrentVersion'); + final buildLab = currentVersionKey.getValueAsString('BuildLab') ?? ''; + final buildLabEx = currentVersionKey.getValueAsString('BuildLabEx') ?? ''; + final digitalProductIdValue = + currentVersionKey.getValue('DigitalProductId'); + final digitalProductId = digitalProductIdValue != null && + digitalProductIdValue.data is Uint8List + ? digitalProductIdValue.data as Uint8List + : Uint8List.fromList([]); + final displayVersion = + currentVersionKey.getValueAsString('DisplayVersion') ?? ''; + final editionId = currentVersionKey.getValueAsString('EditionID') ?? ''; + final installDate = DateTime.fromMillisecondsSinceEpoch( + 1000 * (currentVersionKey.getValueAsInt('InstallDate') ?? 0)); + final productId = currentVersionKey.getValueAsString('ProductID') ?? ''; + var productName = currentVersionKey.getValueAsString('ProductName') ?? ''; + final registeredOwner = + currentVersionKey.getValueAsString('RegisteredOwner') ?? ''; + final releaseId = currentVersionKey.getValueAsString('ReleaseId') ?? ''; + + final sqmClientKey = Registry.openPath(RegistryHive.localMachine, + path: r'SOFTWARE\Microsoft\SQMClient'); + final machineId = sqmClientKey.getValueAsString('MachineId') ?? ''; + + GetSystemInfo(systemInfo); + + // Use `RtlGetVersion` from `ntdll.dll` to get the Windows version. + RtlGetVersion(osVersionInfo); + + // Handle [productName] for Windows 11 separately (as per Raymond Chen's comment). + // https://stackoverflow.com/questions/69460588/how-can-i-find-the-windows-product-name-in-windows-11 + if (osVersionInfo.ref.dwBuildNumber >= 22000) { + productName = productName.replaceAll('10', '11'); + } + final data = WindowsDeviceInfo( + numberOfCores: systemInfo.ref.dwNumberOfProcessors, + computerName: getComputerName(), + systemMemoryInMegabytes: getSystemMemoryInMegabytes(), + userName: getUserName(), + majorVersion: osVersionInfo.ref.dwMajorVersion, + minorVersion: osVersionInfo.ref.dwMinorVersion, + buildNumber: osVersionInfo.ref.dwBuildNumber, + platformId: osVersionInfo.ref.dwPlatformId, + csdVersion: osVersionInfo.ref.szCSDVersion, + servicePackMajor: osVersionInfo.ref.wServicePackMajor, + servicePackMinor: osVersionInfo.ref.wServicePackMinor, + suitMask: osVersionInfo.ref.wSuiteMask, + productType: osVersionInfo.ref.wProductType, + reserved: osVersionInfo.ref.wReserved, + buildLab: buildLab, + buildLabEx: buildLabEx, + digitalProductId: digitalProductId, + displayVersion: displayVersion, + editionId: editionId, + installDate: installDate, + productId: productId, + productName: productName, + registeredOwner: registeredOwner, + releaseId: releaseId, + deviceId: machineId, + ); + return data; + } finally { + free(systemInfo); + free(osVersionInfo); + } + } + + @visibleForTesting + int getSystemMemoryInMegabytes() { + final memoryInKilobytes = calloc(); + try { + final result = GetPhysicallyInstalledSystemMemory(memoryInKilobytes); + if (result != 0) { + return memoryInKilobytes.value ~/ 1024; + } else { + developer.log('Failed to get system memory', error: GetLastError()); + return 0; + } + } finally { + free(memoryInKilobytes); + } + } + + @visibleForTesting + String getComputerName() { + // We call this a first time to get the length of the string in characters, + // so we can allocate sufficient memory. + final nSize = calloc(); + GetComputerNameEx( + COMPUTER_NAME_FORMAT.ComputerNameDnsFullyQualified, nullptr, nSize); + + // Now allocate memory for a native string and call this a second time. + final lpBuffer = wsalloc(nSize.value); + try { + final result = GetComputerNameEx( + COMPUTER_NAME_FORMAT.ComputerNameDnsFullyQualified, lpBuffer, nSize); + + if (result != 0) { + return lpBuffer.toDartString(); + } else { + developer.log('Failed to get computer name', error: GetLastError()); + return ""; + } + } finally { + free(lpBuffer); + free(nSize); + } + } + + @visibleForTesting + String getUserName() { + const maxLength = 256; // defined as UNLEN in Lmcons.h + final lpBuffer = wsalloc(maxLength + 1); // allow for terminating null + final pcbBuffer = calloc()..value = maxLength + 1; + try { + final result = GetUserName(lpBuffer, pcbBuffer); + if (result != 0) { + return lpBuffer.toDartString(); + } else { + developer.log('Failed to get user name', error: GetLastError()); + return ""; + } + } finally { + free(pcbBuffer); + free(lpBuffer); + } + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/android_device_info.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/android_device_info.dart new file mode 100755 index 00000000..d14c8c59 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/android_device_info.dart @@ -0,0 +1,253 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Information derived from `android.os.Build`. +/// +/// See: https://developer.android.com/reference/android/os/Build.html +class AndroidDeviceInfo extends BaseDeviceInfo { + AndroidDeviceInfo._({ + required Map data, + required this.version, + required this.board, + required this.bootloader, + required this.brand, + required this.device, + required this.display, + required this.fingerprint, + required this.hardware, + required this.host, + required this.id, + required this.manufacturer, + required this.model, + required this.product, + required this.name, + required List supported32BitAbis, + required List supported64BitAbis, + required List supportedAbis, + required this.tags, + required this.type, + required this.isPhysicalDevice, + required List systemFeatures, + required this.serialNumber, + required this.isLowRamDevice, + }) : supported32BitAbis = List.unmodifiable(supported32BitAbis), + supported64BitAbis = List.unmodifiable(supported64BitAbis), + supportedAbis = List.unmodifiable(supportedAbis), + systemFeatures = List.unmodifiable(systemFeatures), + super(data); + + /// Android operating system version values derived from `android.os.Build.VERSION`. + final AndroidBuildVersion version; + + /// The name of the underlying board, like "goldfish". + /// https://developer.android.com/reference/android/os/Build#BOARD + final String board; + + /// The system bootloader version number. + /// https://developer.android.com/reference/android/os/Build#BOOTLOADER + final String bootloader; + + /// The consumer-visible brand with which the product/hardware will be associated, if any. + /// https://developer.android.com/reference/android/os/Build#BRAND + final String brand; + + /// The name of the industrial design. + /// https://developer.android.com/reference/android/os/Build#DEVICE + final String device; + + /// A build ID string meant for displaying to the user. + /// https://developer.android.com/reference/android/os/Build#DISPLAY + final String display; + + /// A string that uniquely identifies this build. + /// https://developer.android.com/reference/android/os/Build#FINGERPRINT + final String fingerprint; + + /// The name of the hardware (from the kernel command line or /proc). + /// https://developer.android.com/reference/android/os/Build#HARDWARE + final String hardware; + + /// Hostname. + /// https://developer.android.com/reference/android/os/Build#HOST + final String host; + + /// Either a changelist number, or a label like "M4-rc20". + /// https://developer.android.com/reference/android/os/Build#ID + final String id; + + /// The manufacturer of the product/hardware. + /// https://developer.android.com/reference/android/os/Build#MANUFACTURER + final String manufacturer; + + /// The end-user-visible name for the end product. + /// https://developer.android.com/reference/android/os/Build#MODEL + final String model; + + /// The name of the overall product. + /// https://developer.android.com/reference/android/os/Build#PRODUCT + final String product; + + /// The name of the device. + /// https://developer.android.com/reference/android/provider/Settings.Global#DEVICE_NAME + final String name; + + /// An ordered list of 32 bit ABIs supported by this device. + /// Available only on Android L (API 21) and newer + /// https://developer.android.com/reference/android/os/Build#SUPPORTED_32_BIT_ABIS + final List supported32BitAbis; + + /// An ordered list of 64 bit ABIs supported by this device. + /// Available only on Android L (API 21) and newer + /// https://developer.android.com/reference/android/os/Build#SUPPORTED_64_BIT_ABIS + final List supported64BitAbis; + + /// An ordered list of ABIs supported by this device. + /// Available only on Android L (API 21) and newer + /// https://developer.android.com/reference/android/os/Build#SUPPORTED_ABIS + final List supportedAbis; + + /// Comma-separated tags describing the build, like "unsigned,debug". + /// https://developer.android.com/reference/android/os/Build#TAGS + final String tags; + + /// The type of build, like "user" or "eng". + /// https://developer.android.com/reference/android/os/Build#TYPE + final String type; + + /// `false` if the application is running in an emulator, `true` otherwise. + final bool isPhysicalDevice; + + /// Describes what features are available on the current device. + /// + /// This can be used to check if the device has, for example, a front-facing + /// camera, or a touchscreen. However, in many cases this is not the best + /// API to use. For example, if you are interested in bluetooth, this API + /// can tell you if the device has a bluetooth radio, but it cannot tell you + /// if bluetooth is currently enabled, or if you have been granted the + /// necessary permissions to use it. Please *only* use this if there is no + /// other way to determine if a feature is supported. + /// + /// This data comes from Android's PackageManager.getSystemAvailableFeatures, + /// and many of the common feature strings to look for are available in + /// PackageManager's public documentation: + /// https://developer.android.com/reference/android/content/pm/PackageManager + final List systemFeatures; + + /// Hardware serial number of the device, if available + /// + /// There are special restrictions on this identifier, more info here: + /// https://developer.android.com/reference/android/os/Build#getSerial() + final String serialNumber; + + /// `true` if the application is running on a low-RAM device, `false` otherwise. + final bool isLowRamDevice; + + /// Deserializes from the message received from [_kChannel]. + static AndroidDeviceInfo fromMap(Map map) { + return AndroidDeviceInfo._( + data: map, + version: AndroidBuildVersion._fromMap( + map['version']?.cast() ?? {}), + board: map['board'], + bootloader: map['bootloader'], + brand: map['brand'], + device: map['device'], + display: map['display'], + fingerprint: map['fingerprint'], + hardware: map['hardware'], + host: map['host'], + id: map['id'], + manufacturer: map['manufacturer'], + model: map['model'], + product: map['product'], + name: map['name'] ?? '', + supported32BitAbis: _fromList(map['supported32BitAbis'] ?? []), + supported64BitAbis: _fromList(map['supported64BitAbis'] ?? []), + supportedAbis: _fromList(map['supportedAbis'] ?? []), + tags: map['tags'], + type: map['type'], + isPhysicalDevice: map['isPhysicalDevice'], + systemFeatures: _fromList(map['systemFeatures'] ?? []), + serialNumber: map['serialNumber'], + isLowRamDevice: map['isLowRamDevice'], + ); + } + + /// Deserializes message as List + static List _fromList(List message) { + final list = message.takeWhile((item) => item != null).toList(); + return List.from(list); + } +} + +/// Version values of the current Android operating system build derived from +/// `android.os.Build.VERSION`. +/// +/// See: https://developer.android.com/reference/android/os/Build.VERSION.html +class AndroidBuildVersion { + const AndroidBuildVersion._({ + this.baseOS, + required this.codename, + required this.incremental, + required this.previewSdkInt, + required this.release, + required this.sdkInt, + this.securityPatch, + }); + + /// The base OS build the product is based on. + /// Available only on Android M (API 23) and newer + final String? baseOS; + + /// The current development codename, or the string "REL" if this is a release build. + final String codename; + + /// The internal value used by the underlying source control to represent this build. + /// Available only on Android M (API 23) and newer + final String incremental; + + /// The developer preview revision of a pre-release SDK. + final int? previewSdkInt; + + /// The user-visible version string. + final String release; + + /// The user-visible SDK version of the framework. + /// + /// Possible values are defined in: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html + final int sdkInt; + + /// The user-visible security patch level. + /// Available only on Android M (API 23) and newer + final String? securityPatch; + + /// Serializes [ AndroidBuildVersion ] to map. + @Deprecated('[toMap] method will be discontinued') + Map toMap() { + return { + 'baseOS': baseOS, + 'sdkInt': sdkInt, + 'release': release, + 'codename': codename, + 'incremental': incremental, + 'previewSdkInt': previewSdkInt, + 'securityPatch': securityPatch, + }; + } + + /// Deserializes from the map message received from [_kChannel]. + static AndroidBuildVersion _fromMap(Map map) { + return AndroidBuildVersion._( + baseOS: map['baseOS'], + codename: map['codename'], + incremental: map['incremental'], + previewSdkInt: map['previewSdkInt'], + release: map['release'], + sdkInt: map['sdkInt'], + securityPatch: map['securityPatch'], + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/ios_device_info.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/ios_device_info.dart new file mode 100755 index 00000000..aaf654a7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/ios_device_info.dart @@ -0,0 +1,123 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Information derived from `UIDevice`. +/// +/// See: https://developer.apple.com/documentation/uikit/uidevice +class IosDeviceInfo extends BaseDeviceInfo { + /// IOS device info class. + IosDeviceInfo._({ + required Map data, + required this.name, + required this.systemName, + required this.systemVersion, + required this.model, + required this.modelName, + required this.localizedModel, + this.identifierForVendor, + required this.isPhysicalDevice, + required this.isiOSAppOnMac, + required this.utsname, + }) : super(data); + + /// Device name. + /// + /// On iOS < 16 returns user-assigned device name + /// On iOS >= 16 returns a generic device name if project has + /// no entitlement to get user-assigned device name. + /// https://developer.apple.com/documentation/uikit/uidevice/1620015-name + final String name; + + /// The name of the current operating system. + /// https://developer.apple.com/documentation/uikit/uidevice/1620054-systemname + final String systemName; + + /// The current operating system version. + /// https://developer.apple.com/documentation/uikit/uidevice/1620043-systemversion + final String systemVersion; + + /// Device model according to OS + /// https://developer.apple.com/documentation/uikit/uidevice/1620044-model + final String model; + + /// Commercial or user-known model name + /// Examples: `iPhone 16 Pro`, `iPad Pro 11-Inch 3` + final String modelName; + + /// Localized name of the device model. + /// https://developer.apple.com/documentation/uikit/uidevice/1620029-localizedmodel + final String localizedModel; + + /// Unique UUID value identifying the current device. + /// https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor + final String? identifierForVendor; + + /// `false` if the application is running in a simulator, `true` otherwise. + final bool isPhysicalDevice; + + /// that indicates whether the process is an iPhone or iPad app running on a Mac. + /// https://developer.apple.com/documentation/foundation/nsprocessinfo/3608556-iosapponmac + final bool isiOSAppOnMac; + + /// Operating system information derived from `sys/utsname.h`. + final IosUtsname utsname; + + /// Deserializes from the map message received from [_kChannel]. + static IosDeviceInfo fromMap(Map map) { + return IosDeviceInfo._( + data: map, + name: map['name'], + systemName: map['systemName'], + systemVersion: map['systemVersion'], + model: map['model'], + modelName: map['modelName'], + localizedModel: map['localizedModel'], + identifierForVendor: map['identifierForVendor'], + isPhysicalDevice: map['isPhysicalDevice'], + isiOSAppOnMac: map['isiOSAppOnMac'], + utsname: + IosUtsname._fromMap(map['utsname']?.cast() ?? {}), + ); + } +} + +/// Information derived from `utsname`. +/// See http://pubs.opengroup.org/onlinepubs/7908799/xsh/sysutsname.h.html for details. +class IosUtsname { + const IosUtsname._({ + required this.sysname, + required this.nodename, + required this.release, + required this.version, + required this.machine, + }); + + /// Operating system name. + final String sysname; + + /// Network node name. + final String nodename; + + /// Release level. + final String release; + + /// Version level. + final String version; + + /// Hardware type (e.g. 'iPhone7,1' for iPhone 6 Plus). + final String machine; + + /// Deserializes from the map message received from [_kChannel]. + static IosUtsname _fromMap(Map map) { + return IosUtsname._( + sysname: map['sysname'], + nodename: map['nodename'], + release: map['release'], + version: map['version'], + machine: map['machine'], + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/linux_device_info.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/linux_device_info.dart new file mode 100755 index 00000000..f7aa1088 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/linux_device_info.dart @@ -0,0 +1,168 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Device information for a Linux system. +/// +/// See: +/// - https://www.freedesktop.org/software/systemd/man/os-release.html +/// - https://www.freedesktop.org/software/systemd/man/machine-id.html +class LinuxDeviceInfo implements BaseDeviceInfo { + /// Constructs a LinuxDeviceInfo. + LinuxDeviceInfo({ + required this.name, + this.version, + required this.id, + this.idLike, + this.versionCodename, + this.versionId, + required this.prettyName, + this.buildId, + this.variant, + this.variantId, + required this.machineId, + }); + + /// A string identifying the operating system, without a version component, + /// and suitable for presentation to the user. + /// + /// Examples: 'Fedora', 'Debian GNU/Linux'. + /// + /// If not set, defaults to 'Linux'. + final String name; + + /// A string identifying the operating system version, excluding any OS name + /// information, possibly including a release code name, and suitable for + /// presentation to the user. + /// + /// Examples: '17', '17 (Beefy Miracle)'. + /// + /// This field is optional and may be null on some systems. + final String? version; + + /// A lower-case string identifying the operating system, excluding any + /// version information and suitable for processing by scripts or usage in + /// generated filenames. + /// + /// The ID contains no spaces or other characters outside of 0–9, a–z, '.', + /// '_' and '-'. + /// + /// Examples: 'fedora', 'debian'. + /// + /// If not set, defaults to 'linux'. + final String id; + + /// A space-separated list of operating system identifiers in the same syntax + /// as the [id] value. It lists identifiers of operating systems that are + /// closely related to the local operating system in regards to packaging + /// and programming interfaces, for example listing one or more OS identifiers + /// the local OS is a derivative from. + /// + /// Examples: an operating system with [id] 'centos', would list 'rhel' and + /// 'fedora', and an operating system with [id] 'ubuntu' would list 'debian'. + /// + /// This field is optional and may be null on some systems. + final List? idLike; + + /// A lower-case string identifying the operating system release code name, + /// excluding any OS name information or release version, and suitable for + /// processing by scripts or usage in generated filenames. + /// + /// The codename contains no spaces or other characters outside of 0–9, a–z, + /// '.', '_' and '-'. + /// + /// Examples: 'buster', 'xenial'. + /// + /// This field is optional and may be null on some systems. + final String? versionCodename; + + /// A lower-case string identifying the operating system version, excluding + /// any OS name information or release code name, and suitable for processing + /// by scripts or usage in generated filenames. + /// + /// The version is mostly numeric, and contains no spaces or other characters + /// outside of 0–9, a–z, '.', '_' and '-'. + /// + /// Examples: '17', '11.04'. + /// + /// This field is optional and may be null on some systems. + final String? versionId; + + /// A pretty operating system name in a format suitable for presentation to + /// the user. May or may not contain a release code name or OS version of some + /// kind, as suitable. + /// + /// Examples: 'Fedora 17 (Beefy Miracle)'. + /// + /// If not set, defaults to 'Linux'. + final String prettyName; + + /// A string uniquely identifying the system image used as the origin for a + /// distribution (it is not updated with system updates). The field can be + /// identical between different [versionId]s as `buildId` is an only a unique + /// identifier to a specific version. + /// + /// Examples: '2013-03-20.3', '201303203'. + /// + /// This field is optional and may be null on some systems. + final String? buildId; + + /// A string identifying a specific variant or edition of the operating system + /// suitable for presentation to the user. This field may be used to inform + /// the user that the configuration of this system is subject to a specific + /// divergent set of rules or default configuration settings. + /// + /// Examples: 'Server Edition', 'Smart Refrigerator Edition'. + /// + /// Note: this field is for display purposes only. The [variantId] field + /// should be used for making programmatic decisions. + /// + /// This field is optional and may be null on some systems. + final String? variant; + + /// A lower-case string identifying a specific variant or edition of the + /// operating system. This may be interpreted in order to determine a + /// divergent default configuration. + /// + /// The variant ID contains no spaces or other characters outside of 0–9, a–z, + /// '.', '_' and '-'. + /// + /// Examples: 'server', 'embedded'. + /// + /// This field is optional and may be null on some systems. + final String? variantId; + + /// A unique machine ID of the local system that is set during installation or + /// boot. The machine ID is hexadecimal, 32-character, lowercase ID. When + /// decoded from hexadecimal, this corresponds to a 16-byte/128-bit value. + final String? machineId; + + @override + // ignore: deprecated_member_use_from_same_package + Map get data => toMap(); + + @Deprecated('Use [data] getter instead') + @override + Map toMap() { + return { + 'name': name, + 'version': version, + 'id': id, + 'idLike': idLike, + 'versionCodename': versionCodename, + 'versionId': versionId, + 'prettyName': prettyName, + 'buildId': buildId, + 'variant': variant, + 'variantId': variantId, + 'machineId': machineId, + }; + } + + @override + String toString() { + return 'LinuxDeviceInfo(name: $name, version: $version, id: $id, idLike: $idLike, versionCodename: $versionCodename, versionId: $versionId, prettyName: $prettyName, buildId: $buildId, variant: $variant, variantId: $variantId, machineId: $machineId)'; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/macos_device_info.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/macos_device_info.dart new file mode 100755 index 00000000..7725c5d1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/macos_device_info.dart @@ -0,0 +1,97 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Object encapsulating MACOS device information. +class MacOsDeviceInfo extends BaseDeviceInfo { + /// Constructs a MacOsDeviceInfo. + MacOsDeviceInfo._({ + required Map data, + required this.computerName, + required this.hostName, + required this.arch, + required this.model, + required this.modelName, + required this.kernelVersion, + required this.osRelease, + required this.majorVersion, + required this.minorVersion, + required this.patchVersion, + required this.activeCPUs, + required this.memorySize, + required this.cpuFrequency, + required this.systemGUID, + }) : super(data); + + /// Name given to the local machine. + final String computerName; + + /// Operating system type + final String hostName; + + /// Machine cpu architecture + /// Note, that on Apple Silicon Macs can return `x86_64` if app runs via Rosetta + final String arch; + + /// Device model identifier + /// Examples: `MacBookPro18,3`, `Mac16,2`. + final String model; + + /// Device model name + /// Examples: `MacBook Pro (16-inch, 2021)`, `iMac (24-inch, 2024)`. + final String modelName; + + /// Machine Kernel version. + /// Examples: + /// `Darwin Kernel Version 15.3.0: Thu Dec 10 18:40:58 PST 2015; root:xnu-3248.30.4~1/RELEASE_X86_64` + /// or + /// `Darwin Kernel Version 15.0.0: Wed Dec 9 22:19:38 PST 2015; root:xnu-3248.31.3~2/RELEASE_ARM64_S8000` + final String kernelVersion; + + /// Operating system release number + final String osRelease; + + /// The major release number, such as 10 in version 10.9.3. + final int majorVersion; + + /// The minor release number, such as 9 in version 10.9.3. + final int minorVersion; + + /// The update release number, such as 3 in version 10.9.3. + final int patchVersion; + + /// Number of active CPUs + final int activeCPUs; + + /// Machine's memory size + final int memorySize; + + /// Device CPU Frequency + final int cpuFrequency; + + /// Device GUID + final String? systemGUID; + + /// Constructs a [MacOsDeviceInfo] from a Map of dynamic. + static MacOsDeviceInfo fromMap(Map map) { + return MacOsDeviceInfo._( + data: map, + computerName: map['computerName'], + hostName: map['hostName'], + arch: map['arch'], + model: map['model'], + modelName: map['modelName'], + kernelVersion: map['kernelVersion'], + osRelease: map['osRelease'], + majorVersion: map['majorVersion'], + minorVersion: map['minorVersion'], + patchVersion: map['patchVersion'], + activeCPUs: map['activeCPUs'], + memorySize: map['memorySize'], + cpuFrequency: map['cpuFrequency'], + systemGUID: map['systemGUID'], + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/web_browser_info.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/web_browser_info.dart new file mode 100755 index 00000000..03fa7f83 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/web_browser_info.dart @@ -0,0 +1,188 @@ +// Copyright 2020 The Flutter Community Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// List of supported browsers +enum BrowserName { + /// Mozilla Firefox + firefox, + + /// Samsumg Internet Browser + samsungInternet, + + /// Opera Web Browser + opera, + + /// Microsoft Internet Explorer + msie, + + /// Microsoft Edge + edge, + + /// Google Chrome + chrome, + + /// Apple Safari + safari, + + /// Unknown web browser + unknown, +} + +/// Information derived from `navigator`. +/// +/// See: https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator +class WebBrowserInfo implements BaseDeviceInfo { + /// Web Browser info class. + WebBrowserInfo({ + required this.appCodeName, + required this.appName, + required this.appVersion, + required this.deviceMemory, + required this.language, + required this.languages, + required this.platform, + required this.product, + required this.productSub, + required this.userAgent, + required this.vendor, + required this.vendorSub, + required this.maxTouchPoints, + required this.hardwareConcurrency, + }); + + /// the name of the current browser. + BrowserName get browserName { + return _parseUserAgentToBrowserName(); + } + + /// the internal "code" name of the current browser. + /// Note: Do not rely on this property to return the correct value. + final String? appCodeName; + + /// a DOMString with the official name of the browser. + /// Note: Do not rely on this property to return the correct value. + final String? appName; + + /// the version of the browser as a DOMString. + /// Note: Do not rely on this property to return the correct value. + final String? appVersion; + + /// the amount of device memory in gigabytes. This value is an approximation given by rounding to the nearest power of 2 and dividing that number by 1024. + final double? deviceMemory; + + /// a DOMString representing the preferred language of the user, usually the language of the browser UI. The null value is returned when this is unknown. + final String? language; + + /// an array of DOMString representing the languages known to the user, by order of preference. + final List? languages; + + /// the version of the browser as a DOMString. + /// Note: Do not rely on this property to return the correct value. + final String? platform; + + /// Always returns 'Gecko', on any browser. + /// Note: Do not rely on this property to return the correct value. + /// This property is kept only for compatibility purpose. + final String? product; + + /// the build number of the current browser + /// Note: Do not rely on this property to return the correct value. + final String? productSub; + + /// the build number of the current browser (e.g., "20060909") + final String? userAgent; + + /// the vendor name of the current browser + final String? vendor; + + /// Returns the vendor version number (e.g. "6.1") + /// Note: Do not rely on this property to return the correct value. + final String? vendorSub; + + /// the number of logical processor cores available. + final int? hardwareConcurrency; + + /// the maximum number of simultaneous touch contact points are supported by the current device. + final int? maxTouchPoints; + + /// Deserializes from the map message received from [Navigator]. + static WebBrowserInfo fromMap(Map map) { + return WebBrowserInfo( + appCodeName: map['appCodeName'], + appName: map['appName'], + appVersion: map['appVersion'], + deviceMemory: map['deviceMemory'], + language: map['language'], + languages: map['languages'], + platform: map['platform'], + product: map['product'], + productSub: map['productSub'], + userAgent: map['userAgent'], + vendor: map['vendor'], + vendorSub: map['vendorSub'], + hardwareConcurrency: map['hardwareConcurrency'], + maxTouchPoints: map['maxTouchPoints'], + ); + } + + @Deprecated('use [data] instead') + @override + Map toMap() { + return { + 'browserName': browserName, + 'appCodeName': appCodeName, + 'appName': appName, + 'appVersion': appVersion, + 'deviceMemory': deviceMemory, + 'language': language, + 'languages': languages, + 'platform': platform, + 'product': product, + 'productSub': productSub, + 'userAgent': userAgent, + 'vendor': vendor, + 'vendorSub': vendorSub, + 'hardwareConcurrency': hardwareConcurrency, + 'maxTouchPoints': maxTouchPoints, + }; + } + + BrowserName _parseUserAgentToBrowserName() { + final userAgent = this.userAgent; + if (userAgent == null) { + return BrowserName.unknown; + } else if (userAgent.contains('Firefox')) { + return BrowserName.firefox; + // "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0" + } else if (userAgent.contains('SamsungBrowser')) { + return BrowserName.samsungInternet; + // "Mozilla/5.0 (Linux; Android 9; SAMSUNG SM-G955F Build/PPR1.180610.011) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/9.4 Chrome/67.0.3396.87 Mobile Safari/537.36 + } else if (userAgent.contains('Opera') || userAgent.contains('OPR')) { + return BrowserName.opera; + // "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 OPR/57.0.3098.106" + } else if (userAgent.contains('Trident')) { + return BrowserName.msie; + // "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; Zoom 3.6.0; wbx 1.0.0; rv:11.0) like Gecko" + } else if (userAgent.contains('Edg')) { + return BrowserName.edge; + // https://docs.microsoft.com/en-us/microsoft-edge/web-platform/user-agent-string + // "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.74 Safari/537.36 Edg/79.0.309.43" + // "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299" + } else if (userAgent.contains('Chrome')) { + return BrowserName.chrome; + // "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/66.0.3359.181 Chrome/66.0.3359.181 Safari/537.36" + } else if (userAgent.contains('Safari')) { + return BrowserName.safari; + // "Mozilla/5.0 (iPhone; CPU iPhone OS 11_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1 980x1306" + } else { + return BrowserName.unknown; + } + } + + @override + // ignore: deprecated_member_use_from_same_package + Map get data => toMap(); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/windows_device_info.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/windows_device_info.dart new file mode 100755 index 00000000..d18037b7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/lib/src/model/windows_device_info.dart @@ -0,0 +1,184 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:device_info_plus_platform_interface/model/base_device_info.dart'; + +/// Object encapsulating WINDOWS device information. +class WindowsDeviceInfo implements BaseDeviceInfo { + /// Constructs a [WindowsDeviceInfo]. + const WindowsDeviceInfo({ + required this.computerName, + required this.numberOfCores, + required this.systemMemoryInMegabytes, + required this.userName, + required this.majorVersion, + required this.minorVersion, + required this.buildNumber, + required this.platformId, + required this.csdVersion, + required this.servicePackMajor, + required this.servicePackMinor, + required this.suitMask, + required this.productType, + required this.reserved, + required this.buildLab, + required this.buildLabEx, + required this.digitalProductId, + required this.displayVersion, + required this.editionId, + required this.installDate, + required this.productId, + required this.productName, + required this.registeredOwner, + required this.releaseId, + required this.deviceId, + }); + + /// The computer's fully-qualified DNS name, where available. + final String computerName; + + /// Number of CPU cores on the local machine + final int numberOfCores; + + /// The physically installed memory in the computer. + /// This may not be the same as available memory. + final int systemMemoryInMegabytes; + + final String userName; + + /// The major version number of the operating system. + /// For example, for Windows 2000, the major version number is five. + /// For more information, see the table in Remarks. + /// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfoexw#remarks + final int majorVersion; + + /// The minor version number of the operating system. + /// For example, for Windows 2000, the minor version number is zero. + /// For more information, see the table in Remarks. + /// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfoexw#remarks + final int minorVersion; + + /// The build number of the operating system. + /// For example: + /// - `22000` or greater for Windows 11. + /// - `10240` or greator for Windows 10. + final int buildNumber; + + /// The operating system platform. For Win32 on NT-based operating systems, + /// RtlGetVersion returns the value `VER_PLATFORM_WIN32_NT`. + final int platformId; + + /// The service-pack version string. + /// + /// This member contains a string, such as "Service Pack 3", which indicates + /// the latest service pack installed on the system. + final String csdVersion; + + /// The major version number of the latest service pack installed on the system. + /// For example, for Service Pack 3, the major version number is three. If no + /// service pack has been installed, the value is zero. + final int servicePackMajor; + + /// The minor version number of the latest service pack installed on the + /// system. For example, for Service Pack 3, the minor version number is zero. + final int servicePackMinor; + + /// The product suites available on the system. + final int suitMask; + + /// The product type. This member contains additional information about the + /// system. + final int productType; + + /// Reserved for future use. + final int reserved; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\BuildLab` registry key. For example: + /// `22000.co_release.210604-1628`. + final String buildLab; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\BuildLabEx` registry key. For example: + /// `22000.1.amd64fre.co_release.210604-1628`. + final String buildLabEx; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\DigitalProductId` registry key. + final Uint8List digitalProductId; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\DisplayVersion` registry key. For example: `21H2`. + final String displayVersion; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\EditionID` registry key. + final String editionId; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\InstallDate` registry key. + final DateTime installDate; + + /// Displayed as "Product ID" in Windows Settings. Value of the + /// `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\ProductId` registry key. For example: + /// `00000-00000-0000-AAAAA`. + final String productId; + + /// Value of `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\ProductName` registry key. For example: `Windows 10 Home + /// Single Language`. + final String productName; + + /// Value of the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\RegisteredOwner` registry key. For example: `Microsoft + /// Corporation`. + final String registeredOwner; + + /// Value of the `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows + /// NT\CurrentVersion\ReleaseId` registry key. For example: `1903`. + final String releaseId; + + /// Displayed as "Device ID" in Windows Settings. Value of + /// `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SQMClient\MachineId` registry key. + final String deviceId; + + @Deprecated('use [data] instead') + @override + Map toMap() { + return { + 'computerName': computerName, + 'numberOfCores': numberOfCores, + 'systemMemoryInMegabytes': systemMemoryInMegabytes, + 'userName': userName, + 'majorVersion': majorVersion, + 'minorVersion': minorVersion, + 'buildNumber': buildNumber, + 'platformId': platformId, + 'csdVersion': csdVersion, + 'servicePackMajor': servicePackMajor, + 'servicePackMinor': servicePackMinor, + 'suitMask': suitMask, + 'productType': productType, + 'reserved': reserved, + 'buildLab': buildLab, + 'buildLabEx': buildLabEx, + 'digitalProductId': digitalProductId, + 'displayVersion': displayVersion, + 'editionId': editionId, + 'installDate': installDate, + 'productId': productId, + 'productName': productName, + 'registeredOwner': registeredOwner, + 'releaseId': releaseId, + 'deviceId': deviceId, + }; + } + + @override + // ignore: deprecated_member_use_from_same_package + Map get data => toMap(); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus.podspec b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus.podspec new file mode 100755 index 00000000..a5031bea --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus.podspec @@ -0,0 +1,23 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html +# +Pod::Spec.new do |s| + s.name = 'device_info_plus' + s.version = '0.0.1' + s.summary = 'No-op implementation of the macos device_info_plus to avoid build issues on macos' + s.description = <<-DESC + No-op implementation of the device_info_plus plugin to avoid build issues on macos. +https://github.com/flutter/flutter/issues/46618 + DESC + s.homepage = 'https://github.com/fluttercommunity/plus_plugins/tree/master/packages/device_info_plus' + s.license = { :file => '../LICENSE' } + s.author = { 'Flutter Community' => 'authors@fluttercommunity.dev' } + s.source = { :path => '.' } + s.source_files = 'device_info_plus/Sources/device_info_plus/**/*.swift' + s.public_header_files = 'device_info_plus/Sources/device_info_plus/**/*.h' + s.dependency 'FlutterMacOS' + + s.platform = :osx + s.osx.deployment_target = '10.14' + s.resource_bundles = {'device_info_plus_privacy' => ['device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy']} +end diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Package.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Package.swift new file mode 100755 index 00000000..9cd83e6e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Package.swift @@ -0,0 +1,24 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "device_info_plus", + platforms: [ + .macOS("10.14") + ], + products: [ + .library(name: "device-info-plus", targets: ["device_info_plus"]) + ], + dependencies: [], + targets: [ + .target( + name: "device_info_plus", + dependencies: [], + resources: [ + .process("PrivacyInfo.xcprivacy"), + ] + ) + ] +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/CwlSysctl.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/CwlSysctl.swift new file mode 100755 index 00000000..3f29e31c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/CwlSysctl.swift @@ -0,0 +1,152 @@ +// +// CwlSysctl.swift +// CwlUtils +// +// Created by Matt Gallagher on 2016/02/03. +// Copyright © 2016 Matt Gallagher ( https://www.cocoawithlove.com ). All rights reserved. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +// +import Foundation + +/// A "static"-only namespace around a series of functions that operate on buffers returned from the `Darwin.sysctl` function +public struct Sysctl { + /// Possible errors. + public enum Error: Swift.Error { + case unknown + case malformedUTF8 + case invalidSize + case posixError(POSIXErrorCode) + } + + /// Access the raw data for an array of sysctl identifiers. + public static func data(for keys: [Int32]) throws -> [Int8] { + return try keys.withUnsafeBufferPointer() { keysPointer throws -> [Int8] in + // Preflight the request to get the required data size + var requiredSize = 0 + let preFlightResult = Darwin.sysctl(UnsafeMutablePointer(mutating: keysPointer.baseAddress), UInt32(keys.count), nil, &requiredSize, nil, 0) + if preFlightResult != 0 { + throw POSIXErrorCode(rawValue: errno).map { + return Error.posixError($0) + } ?? Error.unknown + } + + // Run the actual request with an appropriately sized array buffer + let data = Array(repeating: 0, count: requiredSize) + let result = data.withUnsafeBufferPointer() { dataBuffer -> Int32 in + return Darwin.sysctl(UnsafeMutablePointer(mutating: keysPointer.baseAddress), UInt32(keys.count), UnsafeMutableRawPointer(mutating: dataBuffer.baseAddress), &requiredSize, nil, 0) + } + if result != 0 { + throw POSIXErrorCode(rawValue: errno).map { Error.posixError($0) } ?? Error.unknown + } + + return data + } + } + + /// Convert a sysctl name string like "hw.memsize" to the array of `sysctl` identifiers (e.g. [CTL_HW, HW_MEMSIZE]) + public static func keys(for name: String) throws -> [Int32] { + var keysBufferSize = Int(CTL_MAXNAME) + var keysBuffer = Array(repeating: 0, count: keysBufferSize) + try keysBuffer.withUnsafeMutableBufferPointer { (lbp: inout UnsafeMutableBufferPointer) throws in + try name.withCString { (nbp: UnsafePointer) throws in + guard sysctlnametomib(nbp, lbp.baseAddress, &keysBufferSize) == 0 else { + throw POSIXErrorCode(rawValue: errno).map { Error.posixError($0) } ?? Error.unknown + } + } + } + if keysBuffer.count > keysBufferSize { + keysBuffer.removeSubrange(keysBufferSize..(ofType: T.Type, forKeys keys: [Int32]) throws -> T { + let buffer = try data(for: keys) + if buffer.count != MemoryLayout.size { + throw Error.invalidSize + } + return try buffer.withUnsafeBufferPointer() { bufferPtr throws -> T in + guard let baseAddress = bufferPtr.baseAddress else { throw Error.unknown } + return baseAddress.withMemoryRebound(to: T.self, capacity: 1) { $0.pointee } + } + } + + /// Invoke `sysctl` with an array of identifers, interpreting the returned buffer as the specified type. This function will throw `Error.invalidSize` if the size of buffer returned from `sysctl` fails to match the size of `T`. + public static func value(ofType type: T.Type, forKeys keys: Int32...) throws -> T { + return try value(ofType: type, forKeys: keys) + } + + /// Invoke `sysctl` with the specified name, interpreting the returned buffer as the specified type. This function will throw `Error.invalidSize` if the size of buffer returned from `sysctl` fails to match the size of `T`. + public static func value(ofType type: T.Type, forName name: String) throws -> T { + return try value(ofType: type, forKeys: keys(for: name)) + } + + /// Invoke `sysctl` with an array of identifers, interpreting the returned buffer as a `String`. This function will throw `Error.malformedUTF8` if the buffer returned from `sysctl` cannot be interpreted as a UTF8 buffer. + public static func string(for keys: [Int32]) throws -> String { + let optionalString = try data(for: keys).withUnsafeBufferPointer() { dataPointer -> String? in + dataPointer.baseAddress.flatMap { String(validatingUTF8: $0) } + } + guard let s = optionalString else { + throw Error.malformedUTF8 + } + return s + } + + /// Invoke `sysctl` with an array of identifers, interpreting the returned buffer as a `String`. This function will throw `Error.malformedUTF8` if the buffer returned from `sysctl` cannot be interpreted as a UTF8 buffer. + public static func string(for keys: Int32...) throws -> String { + return try string(for: keys) + } + + /// Invoke `sysctl` with the specified name, interpreting the returned buffer as a `String`. This function will throw `Error.malformedUTF8` if the buffer returned from `sysctl` cannot be interpreted as a UTF8 buffer. + public static func string(for name: String) throws -> String { + return try string(for: keys(for: name)) + } + + /// e.g. "MyComputer.local" (from System Preferences -> Sharing -> Computer Name) + public static var hostName: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_HOSTNAME])) ?? "" } + + /// e.g. "x86_64" or "arm64" + public static var machine: String { return (try? Sysctl.string(for: [CTL_HW, HW_MACHINE])) ?? "" } + + /// e.g. "MacBookPro18,2" + public static var model: String { return (try? Sysctl.string(for: [CTL_HW, HW_MODEL])) ?? "" } + + /// e.g. "8" or "2" + public static var activeCPUs: Int32 { return (try? Sysctl.value(ofType: Int32.self, forKeys: [CTL_HW, HW_AVAILCPU])) ?? 0 } + + /// e.g. "15.3.0" or "15.0.0" + public static var osRelease: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_OSRELEASE])) ?? "" } + + /// e.g. "Darwin" or "Darwin" + public static var osType: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_OSTYPE])) ?? "" } + + /// e.g. "15D21" or "13D20" + public static var osVersion: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_OSVERSION])) ?? "" } + + /// e.g. "Darwin Kernel Version 15.3.0: Thu Dec 10 18:40:58 PST 2015; root:xnu-3248.30.4~1/RELEASE_X86_64" or + /// "Darwin Kernel Version 15.0.0: Wed Dec 9 22:19:38 PST 2015; root:xnu-3248.31.3~2/RELEASE_ARM64_S8000" + public static var version: String { return (try? Sysctl.string(for: [CTL_KERN, KERN_VERSION])) ?? "" } + + #if os(macOS) + /// e.g. 199506 (not available on iOS) + public static var osRev: Int32 { return (try? Sysctl.value(ofType: Int32.self, forKeys: [CTL_KERN, KERN_OSREV])) ?? 0 } + + /// e.g. 2659000000 (not available on iOS) + public static var cpuFreq: Int64 { return (try? Sysctl.value(ofType: Int64.self, forName: "hw.cpufrequency")) ?? 0 } + + /// e.g. 25769803776 (not available on iOS) + public static var memSize: UInt64 { return (try? Sysctl.value(ofType: UInt64.self, forKeys: [CTL_HW, HW_MEMSIZE])) ?? 0 } + #endif +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.swift new file mode 100755 index 00000000..288808c1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceIdentifiers.swift @@ -0,0 +1,99 @@ +import Foundation + +// Models list is taken from support.apple.com +// Example of the list with models https://support.apple.com/en-us/102869 + +func getMacModelName(modelNumber: String) -> String { + switch modelNumber { + // MacBook models (2015 and later) + case "MacBook8,1": return "MacBook (12-inch, 2015)" + case "MacBook9,1": return "MacBook (12-inch, 2016)" + case "MacBook10,1": return "MacBook (12-inch, 2017)" + + // MacBook Air models (2013 and later) + case "MacBookAir6,1": return "MacBook Air (11-inch, 2013)" + case "MacBookAir6,2": return "MacBook Air (13-inch, 2013)" + case "MacBookAir7,1": return "MacBook Air (11-inch, 2015)" + case "MacBookAir7,2": return "MacBook Air (13-inch, 2015-2017)" + case "MacBookAir8,1": return "MacBook Air (13-inch, 2018)" + case "MacBookAir8,2": return "MacBook Air (13-inch, 2019)" + case "MacBookAir9,1": return "MacBook Air (13-inch, 2020)" + case "MacBookAir10,1": return "MacBook Air (13-inch, 2020)" + case "Mac14,2": return "MacBook Air (13-inch, 2022)" + case "Mac14,15": return "MacBook Air (15-inch, 2023)" + case "Mac15,12": return "MacBook Air (13-inch, 2024)" + case "Mac15,13": return "MacBook Air (15-inch, 2024)" + + // MacBook Pro models (2012 and later) + case "MacBookPro10,1": return "MacBook Pro (15-inch, 2012-2013)" + case "MacBookPro10,2": return "MacBook Pro (13-inch, 2012-2013)" + case "MacBookPro11,1": return "MacBook Pro (13-inch, 2013-2014)" + case "MacBookPro11,2", "MacBookPro11,3": return "MacBook Pro (15-inch, 2013-2014)" + case "MacBookPro11,4", "MacBookPro11,5": return "MacBook Pro (15-inch, 2015)" + case "MacBookPro12,1": return "MacBook Pro (13-inch, 2015)" + case "MacBookPro13,1": return "MacBook Pro (13-inch, 2016)" + case "MacBookPro13,2": return "MacBook Pro (13-inch, 2016)" + case "MacBookPro13,3": return "MacBook Pro (15-inch, 2016)" + case "MacBookPro14,1": return "MacBook Pro (13-inch, 2017)" + case "MacBookPro14,2": return "MacBook Pro (13-inch, 2017)" + case "MacBookPro14,3": return "MacBook Pro (15-inch, 2017)" + case "MacBookPro15,1", "MacBookPro15,3": return "MacBook Pro (15-inch, 2018-2019)" + case "MacBookPro15,2": return "MacBook Pro (13-inch, 2018-2019)" + case "MacBookPro15,4": return "MacBook Pro (13-inch, 2019)" + case "MacBookPro16,1", "MacBookPro16,4": return "MacBook Pro (16-inch, 2019)" + case "MacBookPro16,2": return "MacBook Pro (13-inch, 2019)" + case "MacBookPro16,3": return "MacBook Pro (13-inch, 2020)" + case "MacBookPro17,1": return "MacBook Pro (13-inch, 2020)" + case "MacBookPro18,1": return "MacBook Pro (14-inch, 2021)" + case "MacBookPro18,2": return "MacBook Pro (16-inch, 2021)" + case "MacBookPro18,3": return "MacBook Pro (16-inch, 2021)" + case "Mac14,5", "Mac14,9": return "MacBook Pro (14-inch, 2023)" + case "Mac14,6", "Mac14,10": return "MacBook Pro (14-inch, 2023)" + case "Mac14,7": return "MacBook Pro (13-inch, 2022)" + case "Mac15,3": return "MacBook Pro (14-inch, 2023)" + case "Mac15,6", "Mac15,8", "Mac15.10": return "MacBook Pro (14-inch, 2023)" + case "Mac15,7", "Mac15,9", "Mac15.11": return "MacBook Pro (16-inch, 2023)" + + // iMac models (2013 and later) + case "iMac13,1": return "iMac (21.5-inch, 2013)" + case "iMac13,2": return "iMac (27-inch, 2013)" + case "iMac14,1": return "iMac (21.5-inch, 2014)" + case "iMac14,2": return "iMac (27-inch, 2014)" + case "iMac14,4": return "iMac (21.5-inch, 2014)" + case "iMac15,1": return "iMac (27-inch, 2014-2015)" + case "iMac16,1","iMac16,2": return "iMac (21.5-inch, 2015)" + case "iMac17,1": return "iMac (27-inch, 2015)" + case "iMac18,1": return "iMac (21.5-inch, 2017)" + case "iMac18,2": return "iMac (21.5-inch, 2017)" + case "iMac18,3": return "iMac (27-inch, 2017)" + case "iMac19,1": return "iMac (27-inch, 2019)" + case "iMac19,2": return "iMac (21.5-inch, 2019)" + case "iMac20,1", "iMac20,2": return "iMac (27-inch, 2020)" + case "iMac21,1", "iMac21,2": return "iMac (24-inch, 2021)" + case "Mac15,4", "Mac15,5": return "iMac (24-inch, 2023)" + case "Mac16,2", "Mac16,3": return "iMac (24-inch, 2024)" + + // Mac mini models (2012 and later) + case "MacMini6,1", "MacMini6,2": return "Mac mini (2012)" + case "MacMini7,1": return "Mac mini (2014)" + case "MacMini8,1": return "Mac mini (2018)" + case "MacMini9,1": return "Mac mini (2020)" + case "Mac14,12": return "Mac mini (2023)" + case "Mac14,3": return "Mac mini (2023)" + case "Mac16,15", "Mac16,10": return "Mac mini (2024)" + + // Mac Pro models (2013 and later) + case "MacPro6,1": return "Mac Pro (Late 2013)" + case "MacPro7,1": return "Mac Pro (2019)" + case "Mac14,8": return "Mac Pro (2023)" + + // iMac Pro + case "iMacPro1,1": return "iMac Pro (2017)" + + // Mac Studio (2022 and newer) + case "Mac13,1", "Mac13,2": return "Mac Studio (2022)" + case "Mac14,13", "Mac14,14": return "Mac Studio (2023)" + + default: return "Unknown Model" + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift new file mode 100755 index 00000000..a1f68236 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/DeviceInfoPlusMacosPlugin.swift @@ -0,0 +1,54 @@ +import Cocoa +import FlutterMacOS + +public class DeviceInfoPlusMacosPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "dev.fluttercommunity.plus/device_info", binaryMessenger: registrar.messenger) + let instance = DeviceInfoPlusMacosPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getDeviceInfo": + handleDeviceInfo(result: result) + default: + result(FlutterMethodNotImplemented) + } + } + + private func handleDeviceInfo(result: @escaping FlutterResult)-> Void{ + let computerName = Host.current().localizedName ?? Sysctl.hostName + let hostName = Sysctl.osType + let arch = Sysctl.machine + let model = Sysctl.model + let modelName = getMacModelName(modelNumber: Sysctl.model) + let kernelVersion = Sysctl.version + let osRelease = ProcessInfo.processInfo.operatingSystemVersionString + let osVersion = ProcessInfo.processInfo.operatingSystemVersion; + let majorVersion = osVersion.majorVersion + let minorVersion = osVersion.minorVersion + let patchVersion = osVersion.patchVersion + let activeCPUs = Sysctl.activeCPUs + let memorySize = Sysctl.memSize + let cpuFrequency = Sysctl.cpuFreq + let guid = SystemUUID.getSystemUUID() + + result([ + "computerName": computerName, + "hostName": hostName, + "arch": arch, + "model": model, + "modelName": modelName, + "kernelVersion": kernelVersion, + "osRelease": osRelease, + "majorVersion": majorVersion, + "minorVersion": minorVersion, + "patchVersion": patchVersion, + "activeCPUs": activeCPUs, + "memorySize": memorySize, + "cpuFrequency": cpuFrequency, + "systemGUID": guid + ] as [String: Any?]) + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy new file mode 100755 index 00000000..918d80be --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/PrivacyInfo.xcprivacy @@ -0,0 +1,12 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/SystemUUID.swift b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/SystemUUID.swift new file mode 100755 index 00000000..0b93b221 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/macos/device_info_plus/Sources/device_info_plus/SystemUUID.swift @@ -0,0 +1,23 @@ +import Foundation + +public struct SystemUUID { + + public static func getSystemUUID() -> String? { + let dev = IOServiceMatching("IOPlatformExpertDevice") + + var platformExpert: io_service_t + if #available(macOS 12, *) { + platformExpert = IOServiceGetMatchingService(kIOMainPortDefault, dev) + } else { + platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, dev) + } + + let serialNumberAsCFString = IORegistryEntryCreateCFProperty(platformExpert, kIOPlatformUUIDKey as CFString, kCFAllocatorDefault, 0) + IOObjectRelease(platformExpert) + let ser: CFTypeRef? = serialNumberAsCFString?.takeUnretainedValue() + if let result = ser as? String { + return result + } + return nil + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/pubspec.yaml new file mode 100755 index 00000000..717ca623 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/pubspec.yaml @@ -0,0 +1,53 @@ +name: device_info_plus +description: Flutter plugin providing detailed information about the device + (make, model, etc.), and Android or iOS version the app is running on. +version: 11.3.0 +homepage: https://github.com/fluttercommunity/plus_plugins +repository: https://github.com/fluttercommunity/plus_plugins/tree/main/packages/device_info_plus/device_info_plus +issue_tracker: https://github.com/fluttercommunity/plus_plugins/labels/device_info_plus +topics: + - device + - information + - utils + +flutter: + plugin: + platforms: + android: + package: dev.fluttercommunity.plus.device_info + pluginClass: DeviceInfoPlusPlugin + ios: + pluginClass: FPPDeviceInfoPlusPlugin + linux: + dartPluginClass: DeviceInfoPlusLinuxPlugin + web: + pluginClass: DeviceInfoPlusWebPlugin + fileName: src/device_info_plus_web.dart + macos: + pluginClass: DeviceInfoPlusMacosPlugin + windows: + dartPluginClass: DeviceInfoPlusWindowsPlugin + +dependencies: + device_info_plus_platform_interface: ^7.0.2 + ffi: ^2.0.1 + file: ">=6.1.4 <8.0.0" + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + meta: ^1.8.0 + web: ^1.0.0 + win32: ^5.5.3 + win32_registry: ^1.1.0 + +dev_dependencies: + flutter_lints: ">=4.0.0 <6.0.0" + flutter_test: + sdk: flutter + mockito: ^5.4.0 + test: ^1.22.0 + +environment: + sdk: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_linux_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_linux_test.dart new file mode 100755 index 00000000..324de590 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_linux_test.dart @@ -0,0 +1,126 @@ +@TestOn('linux') +library device_info_plus_linux_test; + +import 'package:device_info_plus/src/device_info_plus_linux.dart'; +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:file/memory.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('registered instance', () { + DeviceInfoPlusLinuxPlugin.registerWith(); + expect(DeviceInfoPlatform.instance, isA()); + }); + test('os-release', () async { + final fs = MemoryFileSystem.test(); + final file = fs.file('/etc/os-release')..createSync(recursive: true); + file.writeAsStringSync(''' +NAME="A Linux" +VERSION="1.2.3 LTS (A Linux)" +ID=foo +ID_LIKE="bar baz" +VERSION_CODENAME=lts +VERSION_ID="1.2.3-lts" +PRETTY_NAME="A Linux 1.2.3 LTS" +BUILD_ID=1 +VARIANT="Community Edition" +VARIANT_ID=community +HOME_URL="https://www.fluttercommunity.dev/" + '''); + + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.name, equals('A Linux')); + expect(linuxInfo.version, equals('1.2.3 LTS (A Linux)')); + expect(linuxInfo.id, equals('foo')); + expect(linuxInfo.idLike, equals(['bar', 'baz'])); + expect(linuxInfo.versionCodename, equals('lts')); + expect(linuxInfo.versionId, equals('1.2.3-lts')); + expect(linuxInfo.prettyName, equals('A Linux 1.2.3 LTS')); + expect(linuxInfo.buildId, equals('1')); + expect(linuxInfo.variant, equals('Community Edition')); + expect(linuxInfo.variantId, equals('community')); + }); + + test('lsb-release', () async { + final fs = MemoryFileSystem.test(); + final file = fs.file('/etc/lsb-release')..createSync(recursive: true); + file.writeAsStringSync(''' +LSB_VERSION="LSB version" +DISTRIB_ID=distrib-id +DISTRIB_RELEASE=distrib-release +DISTRIB_CODENAME=distrib-codename +DISTRIB_DESCRIPTION="Distrib Description" + '''); + + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.name, equals('Linux')); + expect(linuxInfo.version, equals('LSB version')); + expect(linuxInfo.id, equals('distrib-id')); + expect(linuxInfo.idLike, isNull); + expect(linuxInfo.versionCodename, equals('distrib-codename')); + expect(linuxInfo.versionId, equals('distrib-release')); + expect(linuxInfo.prettyName, 'Distrib Description'); + expect(linuxInfo.buildId, isNull); + expect(linuxInfo.variant, isNull); + expect(linuxInfo.variantId, isNull); + }); + + test('precedence', () async { + final fs = MemoryFileSystem.test(); + final osFile = fs.file('/etc/os-release')..createSync(recursive: true); + osFile.writeAsStringSync(''' +VERSION="OS version" +ID=os + '''); + final lsbFile = fs.file('/etc/lsb-release')..createSync(recursive: true); + lsbFile.writeAsStringSync(''' +LSB_VERSION="LSB version" +DISTRIB_ID=lsb +DISTRIB_RELEASE=distrib-release +DISTRIB_CODENAME=distrib-codename +DISTRIB_DESCRIPTION="Distrib Description" + '''); + + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.name, equals('Linux')); + expect(linuxInfo.version, equals('OS version')); + expect(linuxInfo.id, equals('os')); + expect(linuxInfo.idLike, isNull); + expect(linuxInfo.versionCodename, equals('distrib-codename')); + expect(linuxInfo.versionId, equals('distrib-release')); + expect(linuxInfo.prettyName, 'Distrib Description'); + expect(linuxInfo.buildId, isNull); + expect(linuxInfo.variant, isNull); + expect(linuxInfo.variantId, isNull); + }); + + test('machine-id', () async { + final fs = MemoryFileSystem.test(); + final file = fs.file('/etc/machine-id')..createSync(recursive: true); + file.writeAsStringSync('machine-id'); + + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.machineId, equals('machine-id')); + }); + + test('missing files', () async { + final fs = MemoryFileSystem.test(); + final deviceInfo = DeviceInfoPlusLinuxPlugin(fileSystem: fs); + final linuxInfo = await deviceInfo.linuxInfo(); + expect(linuxInfo.name, equals('Linux')); + expect(linuxInfo.version, isNull); + expect(linuxInfo.id, equals('linux')); + expect(linuxInfo.idLike, isNull); + expect(linuxInfo.versionCodename, isNull); + expect(linuxInfo.versionId, isNull); + expect(linuxInfo.prettyName, 'Linux'); + expect(linuxInfo.buildId, isNull); + expect(linuxInfo.variant, isNull); + expect(linuxInfo.variantId, isNull); + expect(linuxInfo.machineId, isNull); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_web_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_web_test.dart new file mode 100755 index 00000000..b4ed2a4f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_web_test.dart @@ -0,0 +1,39 @@ +@TestOn('browser') +library device_info_plus_web_test; + +import 'package:device_info_plus/src/model/web_browser_info.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('WebBrowserInfo from Map with values', () { + final info = WebBrowserInfo.fromMap( + { + 'appCodeName': 'CODENAME', + 'appName': 'NAME', + 'appVersion': 'VERSION', + 'deviceMemory': 64, + 'language': 'en', + 'languages': ['en', 'es'], + 'platform': 'PLATFORM', + 'product': 'PRODUCT', + 'productSub': 'PRODUCTSUB', + 'userAgent': + 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0', + 'vendor': 'VENDOR', + 'vendorSub': 'VENDORSUB', + 'hardwareConcurrency': 1, + 'maxTouchPoints': 2, + }, + ); + + expect(info.appName, 'NAME'); + expect(info.browserName, BrowserName.firefox); + }); + + test('WebBrowserInfo from empty map', () { + final info = WebBrowserInfo.fromMap({}); + + expect(info.appName, isNull); + expect(info.browserName, BrowserName.unknown); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_windows_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_windows_test.dart new file mode 100755 index 00000000..c3a07ccd --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/device_info_plus_windows_test.dart @@ -0,0 +1,86 @@ +@TestOn('windows') +library device_info_plus_windows_test; + +import 'dart:typed_data'; + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:device_info_plus_platform_interface/device_info_plus_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('registered instance', () { + DeviceInfoPlusWindowsPlugin.registerWith(); + expect(DeviceInfoPlatform.instance, isA()); + }); + test('system-memory-in-megabytes', () async { + final systemMemoryInMegabytes = + DeviceInfoPlusWindowsPlugin().getSystemMemoryInMegabytes(); + + // It's a reasonable expectation that any computer executing this test has + // >512MB RAM + expect(systemMemoryInMegabytes, greaterThan(512)); + }); + test('computer-name', () async { + final computerName = DeviceInfoPlusWindowsPlugin().getComputerName(); + // Must be a non-empty string value. + expect(computerName, isNotEmpty); + }); + test('user-name', () async { + final userName = DeviceInfoPlusWindowsPlugin().getUserName(); + // Must be a non-empty string value. + expect(userName, isNotEmpty); + }); + test('windows information', () async { + final deviceInfo = DeviceInfoPlusWindowsPlugin(); + final windowsInfo = (await deviceInfo.deviceInfo()) as WindowsDeviceInfo; + // Check whether windowsInfo.numberOfProcessors is a positive integer. + expect(windowsInfo.numberOfCores, isPositive); + // Check whether windowsInfo.computerName is a valid non-empty string. + expect(windowsInfo.computerName, isNotEmpty); + // Check whether windowsInfo.systemMemoryInMegabytes is an integer. + expect(windowsInfo.systemMemoryInMegabytes, isA()); + // Check whether windowsInfo.userName is a valid non-empty string. + expect(windowsInfo.userName, isNotEmpty); + // Check for Windows 10 or greater. + expect(windowsInfo.majorVersion, equals(10)); + expect(windowsInfo.minorVersion, equals(0)); + expect(windowsInfo.buildNumber, greaterThan(10240)); + // The value should always be 2 on Windows (VER_PLATFORM_WIN32_NT). + expect(windowsInfo.platformId, equals(2)); + // Check whether windowsInfo.reserved is zero. + expect(windowsInfo.reserved, isZero); + // Check whether windowsInfo.buildLab is a valid non-empty string & starts with windowsInfo.buildNumber. + expect(windowsInfo.buildLab, isNotEmpty); + expect( + windowsInfo.buildLab, + startsWith(windowsInfo.buildNumber.toString()), + ); + // Check whether windowsInfo.buildLabEx is a valid non-empty string & starts with windowsInfo.buildNumber. + expect(windowsInfo.buildLabEx, isNotEmpty); + expect( + windowsInfo.buildLab, + startsWith(windowsInfo.buildNumber.toString()), + ); + // Check whether windowsInfo.digitalProductId is a Uint8List. + expect(windowsInfo.digitalProductId, isA()); + expect(windowsInfo.digitalProductId, isNotEmpty); + // Check whether windowsInfo.editionId is a valid non-empty string. + expect(windowsInfo.editionId, isNotEmpty); + // Check whether windowsInfo.installDate is a valid date in the past. + expect(DateTime.now().isAfter(windowsInfo.installDate), isTrue); + // Check whether windowsInfo.productId is a valid non-empty string & matches 00000-00000-00000-AAAAA format. + expect(windowsInfo.productId, isNotEmpty); + expect( + windowsInfo.productId, + matches(RegExp(r'^([A-Z0-9]{5}-){3}[A-Z0-9]{5}$')), + ); + // Check whether windowsInfo.productName starts with "Windows". + expect(windowsInfo.productName, startsWith('Windows')); + // Check whether windowsInfo.registeredOwner is a valid non-empty string. + expect(windowsInfo.registeredOwner, isNotEmpty); + // Check whether windowsInfo.releaseId is a valid non-empty string. + expect(windowsInfo.releaseId, isNotEmpty); + // Check whether windowsInfo.deviceId is a valid non-empty string. + expect(windowsInfo.deviceId, isNotEmpty); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_fake.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_fake.dart new file mode 100755 index 00000000..46e53acd --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_fake.dart @@ -0,0 +1,42 @@ +part of '../model/android_device_info_test.dart'; + +const _fakeAndroidBuildVersion = { + 'sdkInt': 16, + 'baseOS': 'baseOS', + 'previewSdkInt': 30, + 'release': 'release', + 'codename': 'codename', + 'incremental': 'incremental', + 'securityPatch': 'securityPatch', +}; + +const _fakeSupportedAbis = ['arm64-v8a', 'x86', 'x86_64']; +const _fakeSupported32BitAbis = ['x86 (IA-32)', 'MMX']; +const _fakeSupported64BitAbis = ['x86-64', 'MMX', 'SSSE3']; +const _fakeSystemFeatures = ['FEATURE_AUDIO_PRO', 'FEATURE_AUDIO_OUTPUT']; + +const _fakeAndroidDeviceInfo = { + 'id': 'id', + 'host': 'host', + 'tags': 'tags', + 'type': 'type', + 'model': 'model', + 'board': 'board', + 'brand': 'Google', + 'device': 'device', + 'product': 'product', + "name": "Custom Device Name", + 'display': 'display', + 'hardware': 'hardware', + 'isPhysicalDevice': true, + 'bootloader': 'bootloader', + 'fingerprint': 'fingerprint', + 'manufacturer': 'manufacturer', + 'supportedAbis': _fakeSupportedAbis, + 'systemFeatures': _fakeSystemFeatures, + 'version': _fakeAndroidBuildVersion, + 'supported64BitAbis': _fakeSupported64BitAbis, + 'supported32BitAbis': _fakeSupported32BitAbis, + 'serialNumber': 'SERIAL', + 'isLowRamDevice': false, +}; diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_test.dart new file mode 100755 index 00000000..a5ab4e1e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/android_device_info_test.dart @@ -0,0 +1,52 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'package:device_info_plus/src/model/android_device_info.dart'; +import 'package:flutter_test/flutter_test.dart'; + +part '../model/android_device_info_fake.dart'; + +void main() { + group('$AndroidDeviceInfo fromMap | toMap', () { + test('fromMap should return $AndroidDeviceInfo with correct values', () { + final androidDeviceInfo = + AndroidDeviceInfo.fromMap(_fakeAndroidDeviceInfo); + + expect(androidDeviceInfo.id, 'id'); + expect(androidDeviceInfo.host, 'host'); + expect(androidDeviceInfo.tags, 'tags'); + expect(androidDeviceInfo.type, 'type'); + expect(androidDeviceInfo.model, 'model'); + expect(androidDeviceInfo.board, 'board'); + expect(androidDeviceInfo.brand, 'Google'); + expect(androidDeviceInfo.device, 'device'); + expect(androidDeviceInfo.product, 'product'); + expect(androidDeviceInfo.name, "Custom Device Name"); + expect(androidDeviceInfo.display, 'display'); + expect(androidDeviceInfo.hardware, 'hardware'); + expect(androidDeviceInfo.bootloader, 'bootloader'); + expect(androidDeviceInfo.isPhysicalDevice, isTrue); + expect(androidDeviceInfo.fingerprint, 'fingerprint'); + expect(androidDeviceInfo.manufacturer, 'manufacturer'); + expect(androidDeviceInfo.supportedAbis, _fakeSupportedAbis); + expect(androidDeviceInfo.systemFeatures, _fakeSystemFeatures); + expect(androidDeviceInfo.supported32BitAbis, _fakeSupported32BitAbis); + expect(androidDeviceInfo.supported64BitAbis, _fakeSupported64BitAbis); + expect(androidDeviceInfo.version.sdkInt, 16); + expect(androidDeviceInfo.version.baseOS, 'baseOS'); + expect(androidDeviceInfo.version.previewSdkInt, 30); + expect(androidDeviceInfo.version.release, 'release'); + expect(androidDeviceInfo.version.codename, 'codename'); + expect(androidDeviceInfo.version.incremental, 'incremental'); + expect(androidDeviceInfo.version.securityPatch, 'securityPatch'); + expect(androidDeviceInfo.serialNumber, 'SERIAL'); + expect(androidDeviceInfo.isLowRamDevice, false); + }); + + test('toMap should return map with correct key and map', () { + final androidDeviceInfo = + AndroidDeviceInfo.fromMap(_fakeAndroidDeviceInfo); + + expect(androidDeviceInfo.data, _fakeAndroidDeviceInfo); + }); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/ios_device_info_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/ios_device_info_test.dart new file mode 100755 index 00000000..158a17af --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/ios_device_info_test.dart @@ -0,0 +1,53 @@ +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$IosDeviceInfo fromMap | toMap', () { + late final IosDeviceInfo iosDeviceInfo; + late final Map iosDeviceInfoMap; + + setUpAll(() { + const iosUtsnameMap = { + 'release': 'release', + 'version': 'version', + 'machine': 'machine', + 'sysname': 'sysname', + 'nodename': 'nodename', + }; + iosDeviceInfoMap = { + 'name': 'name', + 'model': 'model', + 'modelName': 'modelName', + 'utsname': iosUtsnameMap, + 'systemName': 'systemName', + 'isPhysicalDevice': true, + 'isiOSAppOnMac': true, + 'systemVersion': 'systemVersion', + 'localizedModel': 'localizedModel', + 'identifierForVendor': 'identifierForVendor', + }; + + iosDeviceInfo = IosDeviceInfo.fromMap(iosDeviceInfoMap); + }); + + test('fromMap should return $IosDeviceInfo with correct values', () { + expect(iosDeviceInfo.name, 'name'); + expect(iosDeviceInfo.model, 'model'); + expect(iosDeviceInfo.modelName, 'modelName'); + expect(iosDeviceInfo.isPhysicalDevice, isTrue); + expect(iosDeviceInfo.isiOSAppOnMac, isTrue); + expect(iosDeviceInfo.systemName, 'systemName'); + expect(iosDeviceInfo.systemVersion, 'systemVersion'); + expect(iosDeviceInfo.localizedModel, 'localizedModel'); + expect(iosDeviceInfo.utsname.release, 'release'); + expect(iosDeviceInfo.utsname.version, 'version'); + expect(iosDeviceInfo.utsname.machine, 'machine'); + expect(iosDeviceInfo.utsname.sysname, 'sysname'); + expect(iosDeviceInfo.utsname.nodename, 'nodename'); + }); + + test('toMap should return map with correct key and map', () { + expect(iosDeviceInfo.data, equals(iosDeviceInfoMap)); + }); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/linux_device_info_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/linux_device_info_test.dart new file mode 100755 index 00000000..761d0202 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/linux_device_info_test.dart @@ -0,0 +1,59 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$LinuxDeviceInfo', () { + test('toMap should return map with correct key and map', () { + final linuxDeviceInfo = LinuxDeviceInfo( + name: 'name', + version: 'version', + id: 'id', + idLike: ['idLike'], + versionCodename: 'versionCodename', + versionId: 'versionId', + prettyName: 'prettyName', + buildId: 'buildId', + variant: 'variant', + variantId: 'variantId', + machineId: 'machineId', + ); + + expect(linuxDeviceInfo.data, { + 'name': 'name', + 'version': 'version', + 'id': 'id', + 'idLike': ['idLike'], + 'versionCodename': 'versionCodename', + 'versionId': 'versionId', + 'prettyName': 'prettyName', + 'buildId': 'buildId', + 'variant': 'variant', + 'variantId': 'variantId', + 'machineId': 'machineId', + }); + }); + + test('toString should return string representation', () { + final linuxDeviceInfo = LinuxDeviceInfo( + name: 'name', + version: 'version', + id: 'id', + idLike: ['idLike'], + versionCodename: 'versionCodename', + versionId: 'versionId', + prettyName: 'prettyName', + buildId: 'buildId', + variant: 'variant', + variantId: 'variantId', + machineId: 'machineId', + ); + + expect( + linuxDeviceInfo.toString(), + 'LinuxDeviceInfo(name: name, version: version, id: id, idLike: [idLike], versionCodename: versionCodename, versionId: versionId, prettyName: prettyName, buildId: buildId, variant: variant, variantId: variantId, machineId: machineId)', + ); + }); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/macos_device_info_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/macos_device_info_test.dart new file mode 100755 index 00000000..ac196762 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/macos_device_info_test.dart @@ -0,0 +1,48 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$MacOsDeviceInfo', () { + group('fromMap | data', () { + const macosDeviceInfoMap = { + 'arch': 'arch', + 'model': 'Mac16,2', + 'modelName': 'iMac (24-inch, 2024)', + 'activeCPUs': 4, + 'memorySize': 16, + 'cpuFrequency': 2, + 'hostName': 'hostName', + 'osRelease': 'osRelease', + 'majorVersion': 10, + 'minorVersion': 9, + 'patchVersion': 3, + 'computerName': 'computerName', + 'kernelVersion': 'kernelVersion', + 'systemGUID': null, + }; + + test('fromMap should return $MacOsDeviceInfo with correct values', () { + final macosDeviceInfo = MacOsDeviceInfo.fromMap(macosDeviceInfoMap); + expect(macosDeviceInfo.arch, 'arch'); + expect(macosDeviceInfo.model, 'Mac16,2'); + expect(macosDeviceInfo.modelName, 'iMac (24-inch, 2024)'); + expect(macosDeviceInfo.activeCPUs, 4); + expect(macosDeviceInfo.memorySize, 16); + expect(macosDeviceInfo.cpuFrequency, 2); + expect(macosDeviceInfo.hostName, 'hostName'); + expect(macosDeviceInfo.osRelease, 'osRelease'); + expect(macosDeviceInfo.majorVersion, 10); + expect(macosDeviceInfo.minorVersion, 9); + expect(macosDeviceInfo.patchVersion, 3); + expect(macosDeviceInfo.systemGUID, isNull); + }); + + test('toMap should return map with correct key and map', () { + final macosDeviceInfo = MacOsDeviceInfo.fromMap(macosDeviceInfoMap); + expect(macosDeviceInfo.data, macosDeviceInfoMap); + }); + }); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/web_browser_info_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/web_browser_info_test.dart new file mode 100755 index 00000000..15b4f497 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/web_browser_info_test.dart @@ -0,0 +1,53 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$WebBrowserInfo', () { + group('fromMap | toMap', () { + const webBrowserInfoMap = { + 'browserName': BrowserName.safari, + 'appCodeName': 'appCodeName', + 'appName': 'appName', + 'appVersion': 'appVersion', + 'deviceMemory': 42.0, + 'language': 'language', + 'languages': ['en', 'es'], + 'platform': 'platform', + 'product': 'product', + 'productSub': 'productSub', + 'userAgent': 'Safari', + 'vendor': 'vendor', + 'vendorSub': 'vendorSub', + 'hardwareConcurrency': 2, + 'maxTouchPoints': 42, + }; + + test('fromMap should return $WebBrowserInfo with correct values', () { + final webBrowserInfo = WebBrowserInfo.fromMap(webBrowserInfoMap); + + expect(webBrowserInfo.browserName, BrowserName.safari); + expect(webBrowserInfo.appCodeName, 'appCodeName'); + expect(webBrowserInfo.appName, 'appName'); + expect(webBrowserInfo.appVersion, 'appVersion'); + expect(webBrowserInfo.deviceMemory, 42); + expect(webBrowserInfo.language, 'language'); + expect(webBrowserInfo.languages, ['en', 'es']); + expect(webBrowserInfo.platform, 'platform'); + expect(webBrowserInfo.product, 'product'); + expect(webBrowserInfo.productSub, 'productSub'); + expect(webBrowserInfo.userAgent, 'Safari'); + expect(webBrowserInfo.vendor, 'vendor'); + expect(webBrowserInfo.vendorSub, 'vendorSub'); + expect(webBrowserInfo.hardwareConcurrency, 2); + expect(webBrowserInfo.maxTouchPoints, 42); + }); + + test('toMap should return map with correct key and map', () { + final webBrowserInfo = WebBrowserInfo.fromMap(webBrowserInfoMap); + expect(webBrowserInfo.data, webBrowserInfoMap); + }); + }); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/windows_device_info_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/windows_device_info_test.dart new file mode 100755 index 00000000..ee452ca8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/device_info_plus/test/model/windows_device_info_test.dart @@ -0,0 +1,67 @@ +// ignore_for_file: deprecated_member_use_from_same_package + +import 'dart:typed_data'; +import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$WindowsDeviceInfo', () { + test('toMap should return map with correct key and map', () { + final windowsDeviceInfo = WindowsDeviceInfo( + computerName: 'computerName', + numberOfCores: 4, + systemMemoryInMegabytes: 16, + userName: 'userName', + majorVersion: 10, + minorVersion: 0, + buildNumber: 10240, + platformId: 1, + csdVersion: 'csdVersion', + servicePackMajor: 1, + servicePackMinor: 0, + suitMask: 1, + productType: 1, + reserved: 1, + buildLab: '22000.co_release.210604-1628', + buildLabEx: '22000.1.amd64fre.co_release.210604-1628', + digitalProductId: Uint8List.fromList([]), + displayVersion: '21H2', + editionId: 'Pro', + installDate: DateTime(2022, 04, 02), + productId: '00000-00000-0000-AAAAA', + productName: 'Windows 10 Pro', + registeredOwner: 'registeredOwner', + releaseId: 'releaseId', + deviceId: 'deviceId', + ); + + expect(windowsDeviceInfo.data, { + 'computerName': 'computerName', + 'numberOfCores': 4, + 'systemMemoryInMegabytes': 16, + 'userName': 'userName', + 'majorVersion': 10, + 'minorVersion': 0, + 'buildNumber': 10240, + 'platformId': 1, + 'csdVersion': 'csdVersion', + 'servicePackMajor': 1, + 'servicePackMinor': 0, + 'suitMask': 1, + 'productType': 1, + 'reserved': 1, + 'buildLab': '22000.co_release.210604-1628', + 'buildLabEx': '22000.1.amd64fre.co_release.210604-1628', + 'digitalProductId': Uint8List.fromList([]), + 'displayVersion': '21H2', + 'editionId': 'Pro', + 'installDate': DateTime(2022, 04, 02), + 'productId': '00000-00000-0000-AAAAA', + 'productName': 'Windows 10 Pro', + 'registeredOwner': 'registeredOwner', + 'releaseId': 'releaseId', + 'deviceId': 'deviceId', + }); + }); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows deleted file mode 120000 index 7c12e441..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/file_selector_windows-0.9.3+4/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/AUTHORS b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/AUTHORS new file mode 100755 index 00000000..557dff97 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/CHANGELOG.md new file mode 100755 index 00000000..204ece58 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/CHANGELOG.md @@ -0,0 +1,104 @@ +## 0.9.3+4 + +* Fixes compile errors under strict standards mode. +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. + +## 0.9.3+3 + +* Updates Pigeon for non-nullable collection type support. +* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. + +## 0.9.3+2 + +* Updates to pigeon 21. +* Updates minimum supported SDK version to Flutter 3.16/Dart 3.2. + +## 0.9.3+1 + +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. +* Migrates `styleFrom` usage in examples off of deprecated `primary` and `onPrimary` parameters. + +## 0.9.3 + +* Adds `getSaveLocation` and deprecates `getSavePath`. + +## 0.9.2 + +* Adds `getDirectoryPaths` implementation. + +## 0.9.1+8 + +* Sets a cmake_policy compatibility version to fix build warnings. +* Updates minimum Flutter version to 3.3. + +## 0.9.1+7 + +* Updates to `pigeon` version 9. + +## 0.9.1+6 + +* Clarifies explanation of endorsement in README. +* Aligns Dart and Flutter SDK constraints. + +## 0.9.1+5 + +* Updates links for the merge of flutter/plugins into flutter/packages. +* Updates example code for `use_build_context_synchronously` lint. +* Updates minimum Flutter version to 3.0. + +## 0.9.1+4 + +* Changes XTypeGroup initialization from final to const. + +## 0.9.1+3 + +* Updates imports for `prefer_relative_imports`. +* Updates minimum Flutter version to 2.10. + +## 0.9.1+2 + +* Fixes the problem that the initial directory does not work after completing a file selection. + +## 0.9.1+1 + +* Updates README for endorsement. +* Updates `flutter_test` to be a `dev_dependencies` entry. + +## 0.9.1 + +* Converts the method channel to Pigeon. + +## 0.9.0 + +* **BREAKING CHANGE**: Methods that take `XTypeGroup`s now throw an + `ArgumentError` if any group is not a wildcard (all filter types null or + empty), but doesn't include any of the filter types supported by Windows. +* Ignores deprecation warnings for upcoming styleFrom button API changes. + +## 0.8.2+2 + +* Updates references to the obsolete master branch. + +## 0.8.2+1 + +* Removes unnecessary imports. +* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors + lint warnings. + +## 0.8.2 + +* Moves source to flutter/plugins, and restructures to allow for unit testing. +* Switches to an internal method channel implementation. + +## 0.0.2+1 + +* Update README + +## 0.0.2 + +* Update SDK constraint to signal compatibility with null safety. + +## 0.0.1 + +* Initial Windows implementation of `file_selector`. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/LICENSE new file mode 100755 index 00000000..c6823b81 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/README.md new file mode 100755 index 00000000..cf2b722b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/README.md @@ -0,0 +1,15 @@ +# file\_selector\_windows + +The Windows implementation of [`file_selector`][1]. + +## Usage + +This package is [endorsed][2], which means you can simply use `file_selector` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. + +[1]: https://pub.dev/packages/file_selector +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/README.md new file mode 100755 index 00000000..96b8bb17 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/get_directory_page.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/get_directory_page.dart new file mode 100755 index 00000000..351b403c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/get_directory_page.dart @@ -0,0 +1,82 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select a directory using `getDirectoryPath`, +/// then displays the selected directory in a dialog. +class GetDirectoryPage extends StatelessWidget { + /// Default Constructor + const GetDirectoryPage({super.key}); + + Future _getDirectoryPath(BuildContext context) async { + const String confirmButtonText = 'Choose'; + final String? directoryPath = + await FileSelectorPlatform.instance.getDirectoryPath( + confirmButtonText: confirmButtonText, + ); + if (directoryPath == null) { + // Operation was canceled by the user. + return; + } + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => TextDisplay(directoryPath), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open a text file'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text('Press to ask user to choose a directory'), + onPressed: () => _getDirectoryPath(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Creates a `TextDisplay`. + const TextDisplay(this.directoryPath, {super.key}); + + /// The path selected in the dialog. + final String directoryPath; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text('Selected Directory'), + content: Scrollbar( + child: SingleChildScrollView( + child: Text(directoryPath), + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/get_multiple_directories_page.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/get_multiple_directories_page.dart new file mode 100755 index 00000000..ebe1f2ac --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/get_multiple_directories_page.dart @@ -0,0 +1,84 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select one or more directories using `getDirectoryPaths`, +/// then displays the selected directories in a dialog. +class GetMultipleDirectoriesPage extends StatelessWidget { + /// Default Constructor + const GetMultipleDirectoriesPage({super.key}); + + Future _getDirectoryPaths(BuildContext context) async { + const String confirmButtonText = 'Choose'; + final List directoriesPaths = + await FileSelectorPlatform.instance.getDirectoryPaths( + confirmButtonText: confirmButtonText, + ); + if (directoriesPaths.isEmpty) { + // Operation was canceled by the user. + return; + } + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => + TextDisplay(directoriesPaths.join('\n')), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Select multiple directories'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text( + 'Press to ask user to choose multiple directories'), + onPressed: () => _getDirectoryPaths(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Creates a `TextDisplay`. + const TextDisplay(this.directoryPaths, {super.key}); + + /// The paths selected in the dialog. + final String directoryPaths; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text('Selected Directories'), + content: Scrollbar( + child: SingleChildScrollView( + child: Text(directoryPaths), + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/home_page.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/home_page.dart new file mode 100755 index 00000000..4715f267 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/home_page.dart @@ -0,0 +1,67 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +/// Home Page of the application. +class HomePage extends StatelessWidget { + /// Default Constructor + const HomePage({super.key}); + + @override + Widget build(BuildContext context) { + final ButtonStyle style = ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ); + return Scaffold( + appBar: AppBar( + title: const Text('File Selector Demo Home Page'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: style, + child: const Text('Open a text file'), + onPressed: () => Navigator.pushNamed(context, '/open/text'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Open an image'), + onPressed: () => Navigator.pushNamed(context, '/open/image'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Open multiple images'), + onPressed: () => Navigator.pushNamed(context, '/open/images'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Save a file'), + onPressed: () => Navigator.pushNamed(context, '/save/text'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Open a get directory dialog'), + onPressed: () => Navigator.pushNamed(context, '/directory'), + ), + const SizedBox(height: 10), + ElevatedButton( + style: style, + child: const Text('Open a get directories dialog'), + onPressed: () => + Navigator.pushNamed(context, '/multi-directories'), + ), + ], + ), + ), + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/main.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/main.dart new file mode 100755 index 00000000..a88f850f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/main.dart @@ -0,0 +1,45 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/material.dart'; + +import 'get_directory_page.dart'; +import 'get_multiple_directories_page.dart'; +import 'home_page.dart'; +import 'open_image_page.dart'; +import 'open_multiple_images_page.dart'; +import 'open_text_page.dart'; +import 'save_text_page.dart'; + +void main() { + runApp(const MyApp()); +} + +/// MyApp is the Main Application. +class MyApp extends StatelessWidget { + /// Default Constructor + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'File Selector Demo', + theme: ThemeData( + primarySwatch: Colors.blue, + visualDensity: VisualDensity.adaptivePlatformDensity, + ), + home: const HomePage(), + routes: { + '/open/image': (BuildContext context) => const OpenImagePage(), + '/open/images': (BuildContext context) => + const OpenMultipleImagesPage(), + '/open/text': (BuildContext context) => const OpenTextPage(), + '/save/text': (BuildContext context) => SaveTextPage(), + '/directory': (BuildContext context) => const GetDirectoryPage(), + '/multi-directories': (BuildContext context) => + const GetMultipleDirectoriesPage() + }, + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/open_image_page.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/open_image_page.dart new file mode 100755 index 00000000..e39dee95 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/open_image_page.dart @@ -0,0 +1,92 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select an image file using +/// `openFiles`, then displays the selected images in a gallery dialog. +class OpenImagePage extends StatelessWidget { + /// Default Constructor + const OpenImagePage({super.key}); + + Future _openImageFile(BuildContext context) async { + const XTypeGroup typeGroup = XTypeGroup( + label: 'images', + extensions: ['jpg', 'png'], + ); + final XFile? file = await FileSelectorPlatform.instance + .openFile(acceptedTypeGroups: [typeGroup]); + if (file == null) { + // Operation was canceled by the user. + return; + } + final String fileName = file.name; + final String filePath = file.path; + + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => ImageDisplay(fileName, filePath), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open an image'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text('Press to open an image file(png, jpg)'), + onPressed: () => _openImageFile(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays an image in a dialog. +class ImageDisplay extends StatelessWidget { + /// Default Constructor. + const ImageDisplay(this.fileName, this.filePath, {super.key}); + + /// The name of the selected file. + final String fileName; + + /// The path to the selected file. + final String filePath; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(fileName), + // On web the filePath is a blob url + // while on other platforms it is a system path. + content: kIsWeb ? Image.network(filePath) : Image.file(File(filePath)), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () { + Navigator.pop(context); + }, + ), + ], + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/open_multiple_images_page.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/open_multiple_images_page.dart new file mode 100755 index 00000000..decb1b64 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/open_multiple_images_page.dart @@ -0,0 +1,104 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select multiple image files using +/// `openFiles`, then displays the selected images in a gallery dialog. +class OpenMultipleImagesPage extends StatelessWidget { + /// Default Constructor + const OpenMultipleImagesPage({super.key}); + + Future _openImageFile(BuildContext context) async { + const XTypeGroup jpgsTypeGroup = XTypeGroup( + label: 'JPEGs', + extensions: ['jpg', 'jpeg'], + ); + const XTypeGroup pngTypeGroup = XTypeGroup( + label: 'PNGs', + extensions: ['png'], + ); + final List files = await FileSelectorPlatform.instance + .openFiles(acceptedTypeGroups: [ + jpgsTypeGroup, + pngTypeGroup, + ]); + if (files.isEmpty) { + // Operation was canceled by the user. + return; + } + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => MultipleImagesDisplay(files), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open multiple images'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text('Press to open multiple images (png, jpg)'), + onPressed: () => _openImageFile(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays a text file in a dialog. +class MultipleImagesDisplay extends StatelessWidget { + /// Default Constructor. + const MultipleImagesDisplay(this.files, {super.key}); + + /// The files containing the images. + final List files; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text('Gallery'), + // On web the filePath is a blob url + // while on other platforms it is a system path. + content: Center( + child: Row( + children: [ + ...files.map( + (XFile file) => Flexible( + child: kIsWeb + ? Image.network(file.path) + : Image.file(File(file.path))), + ) + ], + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () { + Navigator.pop(context); + }, + ), + ], + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/open_text_page.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/open_text_page.dart new file mode 100755 index 00000000..6ffbd28c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/open_text_page.dart @@ -0,0 +1,89 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select a text file using `openFile`, then +/// displays its contents in a dialog. +class OpenTextPage extends StatelessWidget { + /// Default Constructor + const OpenTextPage({super.key}); + + Future _openTextFile(BuildContext context) async { + const XTypeGroup typeGroup = XTypeGroup( + label: 'text', + extensions: ['txt', 'json'], + ); + final XFile? file = await FileSelectorPlatform.instance + .openFile(acceptedTypeGroups: [typeGroup]); + if (file == null) { + // Operation was canceled by the user. + return; + } + final String fileName = file.name; + final String fileContent = await file.readAsString(); + + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => TextDisplay(fileName, fileContent), + ); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open a text file'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + child: const Text('Press to open a text file (json, txt)'), + onPressed: () => _openTextFile(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Default Constructor. + const TextDisplay(this.fileName, this.fileContent, {super.key}); + + /// The name of the selected file. + final String fileName; + + /// The contents of the text file. + final String fileContent; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(fileName), + content: Scrollbar( + child: SingleChildScrollView( + child: Text(fileContent), + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/save_text_page.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/save_text_page.dart new file mode 100755 index 00000000..811ceb98 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/lib/save_text_page.dart @@ -0,0 +1,102 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; +import 'dart:typed_data'; +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter/material.dart'; + +/// Screen that allows the user to select a save location using `getSavePath`, +/// then writes text to a file at that location. +class SaveTextPage extends StatelessWidget { + /// Default Constructor + SaveTextPage({super.key}); + + final TextEditingController _nameController = TextEditingController(); + final TextEditingController _contentController = TextEditingController(); + + Future _saveFile() async { + final String fileName = _nameController.text; + final FileSaveLocation? result = + await FileSelectorPlatform.instance.getSaveLocation( + options: SaveDialogOptions(suggestedName: fileName), + acceptedTypeGroups: const [ + XTypeGroup( + label: 'Plain text', + extensions: ['txt'], + ), + XTypeGroup( + label: 'JSON', + extensions: ['json'], + ), + ], + ); + // Operation was canceled by the user. + if (result == null) { + return; + } + String path = result.path; + // Append an extension based on the selected type group if the user didn't + // include one. + if (!path.split(Platform.pathSeparator).last.contains('.')) { + final XTypeGroup? activeGroup = result.activeFilter; + if (activeGroup != null) { + // The group is one of the groups passed in above, each of which has + // exactly one `extensions` entry. + path = '$path.${activeGroup.extensions!.first}'; + } + } + final String text = _contentController.text; + final Uint8List fileData = Uint8List.fromList(text.codeUnits); + final XFile textFile = XFile.fromData(fileData, name: fileName); + await textFile.saveTo(result.path); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Save text into a file'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: 300, + child: TextField( + minLines: 1, + maxLines: 12, + controller: _nameController, + decoration: const InputDecoration( + hintText: '(Optional) Suggest File Name', + ), + ), + ), + SizedBox( + width: 300, + child: TextField( + minLines: 1, + maxLines: 12, + controller: _contentController, + decoration: const InputDecoration( + hintText: 'Enter File Contents', + ), + ), + ), + const SizedBox(height: 10), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + onPressed: _saveFile, + child: const Text('Press to save a text file'), + ), + ], + ), + ), + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/pubspec.yaml new file mode 100755 index 00000000..2382adc5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/pubspec.yaml @@ -0,0 +1,27 @@ +name: example +description: Example for file_selector_windows implementation. +publish_to: 'none' +version: 1.0.0 + +environment: + sdk: ^3.4.0 + flutter: ">=3.22.0" + +dependencies: + file_selector_platform_interface: ^2.6.0 + file_selector_windows: + # When depending on this package from a real application you should use: + # file_selector_windows: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: .. + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/CMakeLists.txt new file mode 100755 index 00000000..4691cd75 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.14) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + # Enable strict standards mode in the example app, since issues it finds + # may become errors by default in future compiler versions. + target_compile_options(${TARGET} PRIVATE /permissive-) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Enable the test target +set(include_file_selector_windows_tests TRUE) +# Provide an alias for the test target using the name expected by repo tooling. +add_custom_target(unit_tests DEPENDS file_selector_windows_test) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..4f2af69b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,108 @@ +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/flutter/generated_plugins.cmake b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/flutter/generated_plugins.cmake new file mode 100755 index 00000000..a423a024 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..de2d8916 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/Runner.rc b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/Runner.rc new file mode 100755 index 00000000..e5666e02 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/flutter_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..217bf9b6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/flutter_window.cpp @@ -0,0 +1,64 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/flutter_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..7cbf3d3e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/flutter_window.h @@ -0,0 +1,36 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/main.cpp new file mode 100755 index 00000000..1285aabf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/main.cpp @@ -0,0 +1,45 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t* command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/resource.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/resources/app_icon.ico b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/resources/app_icon.ico differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/runner.exe.manifest b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/utils.cpp new file mode 100755 index 00000000..8b8eaa54 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/utils.cpp @@ -0,0 +1,66 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE* unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/utils.h new file mode 100755 index 00000000..6d1cc48f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/utils.h @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/win32_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..34738de2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/win32_window.cpp @@ -0,0 +1,240 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/win32_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/win32_window.h new file mode 100755 index 00000000..0f8bd1b7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/example/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/lib/file_selector_windows.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/lib/file_selector_windows.dart new file mode 100755 index 00000000..150e165f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/lib/file_selector_windows.dart @@ -0,0 +1,129 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; + +import 'src/messages.g.dart'; + +/// An implementation of [FileSelectorPlatform] for Windows. +class FileSelectorWindows extends FileSelectorPlatform { + final FileSelectorApi _hostApi = FileSelectorApi(); + + /// Registers the Windows implementation. + static void registerWith() { + FileSelectorPlatform.instance = FileSelectorWindows(); + } + + @override + Future openFile({ + List? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) async { + final FileDialogResult result = await _hostApi.showOpenDialog( + SelectionOptions( + allowedTypes: _typeGroupsFromXTypeGroups(acceptedTypeGroups), + ), + initialDirectory, + confirmButtonText); + return result.paths.isEmpty ? null : XFile(result.paths.first); + } + + @override + Future> openFiles({ + List? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) async { + final FileDialogResult result = await _hostApi.showOpenDialog( + SelectionOptions( + allowMultiple: true, + allowedTypes: _typeGroupsFromXTypeGroups(acceptedTypeGroups), + ), + initialDirectory, + confirmButtonText); + return result.paths.map((String? path) => XFile(path!)).toList(); + } + + @override + Future getSavePath({ + List? acceptedTypeGroups, + String? initialDirectory, + String? suggestedName, + String? confirmButtonText, + }) async { + final FileSaveLocation? location = await getSaveLocation( + acceptedTypeGroups: acceptedTypeGroups, + options: SaveDialogOptions( + initialDirectory: initialDirectory, + suggestedName: suggestedName, + confirmButtonText: confirmButtonText, + )); + return location?.path; + } + + @override + Future getSaveLocation({ + List? acceptedTypeGroups, + SaveDialogOptions options = const SaveDialogOptions(), + }) async { + final FileDialogResult result = await _hostApi.showSaveDialog( + SelectionOptions( + allowedTypes: _typeGroupsFromXTypeGroups(acceptedTypeGroups), + ), + options.initialDirectory, + options.suggestedName, + options.confirmButtonText); + final int? groupIndex = result.typeGroupIndex; + return result.paths.isEmpty + ? null + : FileSaveLocation(result.paths.first, + activeFilter: + groupIndex == null ? null : acceptedTypeGroups?[groupIndex]); + } + + @override + Future getDirectoryPath({ + String? initialDirectory, + String? confirmButtonText, + }) async { + final FileDialogResult result = await _hostApi.showOpenDialog( + SelectionOptions( + selectFolders: true, + allowedTypes: [], + ), + initialDirectory, + confirmButtonText); + return result.paths.isEmpty ? null : result.paths.first; + } + + @override + Future> getDirectoryPaths({ + String? initialDirectory, + String? confirmButtonText, + }) async { + final FileDialogResult result = await _hostApi.showOpenDialog( + SelectionOptions( + allowMultiple: true, + selectFolders: true, + allowedTypes: [], + ), + initialDirectory, + confirmButtonText); + return result.paths.isEmpty ? [] : List.from(result.paths); + } +} + +List _typeGroupsFromXTypeGroups(List? xtypes) { + return (xtypes ?? []).map((XTypeGroup xtype) { + if (!xtype.allowsAny && (xtype.extensions?.isEmpty ?? true)) { + throw ArgumentError('Provided type group $xtype does not allow ' + 'all files, but does not set any of the Windows-supported filter ' + 'categories. "extensions" must be non-empty for Windows if ' + 'anything is non-empty.'); + } + return TypeGroup( + label: xtype.label ?? '', extensions: xtype.extensions ?? []); + }).toList(); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/pigeons/copyright.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/pigeons/copyright.txt new file mode 100755 index 00000000..1236b63c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/pigeons/messages.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/pigeons/messages.dart new file mode 100755 index 00000000..75ba308d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/pigeons/messages.dart @@ -0,0 +1,62 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon(PigeonOptions( + dartOut: 'lib/src/messages.g.dart', + dartTestOut: 'test/test_api.g.dart', + cppOptions: CppOptions(namespace: 'file_selector_windows'), + cppHeaderOut: 'windows/messages.g.h', + cppSourceOut: 'windows/messages.g.cpp', + copyrightHeader: 'pigeons/copyright.txt', +)) +class TypeGroup { + TypeGroup(this.label, {required this.extensions}); + + String label; + List extensions; +} + +class SelectionOptions { + SelectionOptions({ + this.allowMultiple = false, + this.selectFolders = false, + this.allowedTypes = const [], + }); + bool allowMultiple; + bool selectFolders; + List allowedTypes; +} + +/// The result from an open or save dialog. +class FileDialogResult { + FileDialogResult({required this.paths, this.typeGroupIndex}); + + /// The selected paths. + /// + /// Empty if the dialog was canceled. + List paths; + + /// The type group index (into the list provided in [SelectionOptions]) of + /// the group that was selected when the dialog was confirmed. + /// + /// Null if no type groups were provided, or the dialog was canceled. + int? typeGroupIndex; +} + +@HostApi(dartHostTestHandler: 'TestFileSelectorApi') +abstract class FileSelectorApi { + FileDialogResult showOpenDialog( + SelectionOptions options, + String? initialDirectory, + String? confirmButtonText, + ); + FileDialogResult showSaveDialog( + SelectionOptions options, + String? initialDirectory, + String? suggestedName, + String? confirmButtonText, + ); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/pubspec.yaml new file mode 100755 index 00000000..e750dfa3 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/pubspec.yaml @@ -0,0 +1,35 @@ +name: file_selector_windows +description: Windows implementation of the file_selector plugin. +repository: https://github.com/flutter/packages/tree/main/packages/file_selector/file_selector_windows +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+file_selector%22 +version: 0.9.3+4 + +environment: + sdk: ^3.4.0 + flutter: ">=3.22.0" + +flutter: + plugin: + implements: file_selector + platforms: + windows: + dartPluginClass: FileSelectorWindows + pluginClass: FileSelectorWindows + +dependencies: + cross_file: ^0.3.1 + file_selector_platform_interface: ^2.6.0 + flutter: + sdk: flutter + +dev_dependencies: + build_runner: ^2.3.0 + flutter_test: + sdk: flutter + mockito: ^5.4.4 + pigeon: ^22.4.1 + +topics: + - files + - file-selection + - file-selector diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/test/file_selector_windows_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/test/file_selector_windows_test.dart new file mode 100755 index 00000000..3a451067 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/test/file_selector_windows_test.dart @@ -0,0 +1,466 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:file_selector_windows/file_selector_windows.dart'; +import 'package:file_selector_windows/src/messages.g.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'file_selector_windows_test.mocks.dart'; +import 'test_api.g.dart'; + +@GenerateMocks([TestFileSelectorApi]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + final FileSelectorWindows plugin = FileSelectorWindows(); + late MockTestFileSelectorApi mockApi; + + setUp(() { + mockApi = MockTestFileSelectorApi(); + TestFileSelectorApi.setUp(mockApi); + }); + + test('registered instance', () { + FileSelectorWindows.registerWith(); + expect(FileSelectorPlatform.instance, isA()); + }); + + group('openFile', () { + setUp(() { + when(mockApi.showOpenDialog(any, any, any)) + .thenReturn(FileDialogResult(paths: ['foo'])); + }); + + test('simple call works', () async { + final XFile? file = await plugin.openFile(); + + expect(file!.path, 'foo'); + final VerificationResult result = + verify(mockApi.showOpenDialog(captureAny, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect(options.allowMultiple, false); + expect(options.selectFolders, false); + }); + + test('passes the accepted type groups correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + extensions: ['txt'], + mimeTypes: ['text/plain'], + ); + + const XTypeGroup groupTwo = XTypeGroup( + label: 'image', + extensions: ['jpg'], + mimeTypes: ['image/jpg'], + ); + + await plugin.openFile(acceptedTypeGroups: [group, groupTwo]); + + final VerificationResult result = + verify(mockApi.showOpenDialog(captureAny, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect( + _typeGroupListsMatch(options.allowedTypes, [ + TypeGroup(label: 'text', extensions: ['txt']), + TypeGroup(label: 'image', extensions: ['jpg']), + ]), + true); + }); + + test('passes initialDirectory correctly', () async { + await plugin.openFile(initialDirectory: '/example/directory'); + + verify(mockApi.showOpenDialog(any, '/example/directory', null)); + }); + + test('passes confirmButtonText correctly', () async { + await plugin.openFile(confirmButtonText: 'Open File'); + + verify(mockApi.showOpenDialog(any, null, 'Open File')); + }); + + test('throws for a type group that does not support Windows', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + mimeTypes: ['text/plain'], + ); + + await expectLater( + plugin.openFile(acceptedTypeGroups: [group]), + throwsArgumentError); + }); + + test('allows a wildcard group', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + ); + + await expectLater( + plugin.openFile(acceptedTypeGroups: [group]), completes); + }); + }); + + group('openFiles', () { + setUp(() { + when(mockApi.showOpenDialog(any, any, any)) + .thenReturn(FileDialogResult(paths: ['foo', 'bar'])); + }); + + test('simple call works', () async { + final List file = await plugin.openFiles(); + + expect(file[0].path, 'foo'); + expect(file[1].path, 'bar'); + final VerificationResult result = + verify(mockApi.showOpenDialog(captureAny, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect(options.allowMultiple, true); + expect(options.selectFolders, false); + }); + + test('passes the accepted type groups correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + extensions: ['txt'], + mimeTypes: ['text/plain'], + ); + + const XTypeGroup groupTwo = XTypeGroup( + label: 'image', + extensions: ['jpg'], + mimeTypes: ['image/jpg'], + ); + + await plugin.openFiles(acceptedTypeGroups: [group, groupTwo]); + + final VerificationResult result = + verify(mockApi.showOpenDialog(captureAny, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect( + _typeGroupListsMatch(options.allowedTypes, [ + TypeGroup(label: 'text', extensions: ['txt']), + TypeGroup(label: 'image', extensions: ['jpg']), + ]), + true); + }); + + test('passes initialDirectory correctly', () async { + await plugin.openFiles(initialDirectory: '/example/directory'); + + verify(mockApi.showOpenDialog(any, '/example/directory', null)); + }); + + test('passes confirmButtonText correctly', () async { + await plugin.openFiles(confirmButtonText: 'Open Files'); + + verify(mockApi.showOpenDialog(any, null, 'Open Files')); + }); + + test('throws for a type group that does not support Windows', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + mimeTypes: ['text/plain'], + ); + + await expectLater( + plugin.openFiles(acceptedTypeGroups: [group]), + throwsArgumentError); + }); + + test('allows a wildcard group', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + ); + + await expectLater( + plugin.openFiles(acceptedTypeGroups: [group]), completes); + }); + }); + + group('getDirectoryPath', () { + setUp(() { + when(mockApi.showOpenDialog(any, any, any)) + .thenReturn(FileDialogResult(paths: ['foo'])); + }); + + test('simple call works', () async { + final String? path = await plugin.getDirectoryPath(); + + expect(path, 'foo'); + final VerificationResult result = + verify(mockApi.showOpenDialog(captureAny, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect(options.allowMultiple, false); + expect(options.selectFolders, true); + }); + + test('passes initialDirectory correctly', () async { + await plugin.getDirectoryPath(initialDirectory: '/example/directory'); + + verify(mockApi.showOpenDialog(any, '/example/directory', null)); + }); + + test('passes confirmButtonText correctly', () async { + await plugin.getDirectoryPath(confirmButtonText: 'Open Directory'); + + verify(mockApi.showOpenDialog(any, null, 'Open Directory')); + }); + }); + + group('getDirectoryPaths', () { + setUp(() { + when(mockApi.showOpenDialog(any, any, any)) + .thenReturn(FileDialogResult(paths: ['foo', 'bar'])); + }); + + test('simple call works', () async { + final List paths = await plugin.getDirectoryPaths(); + + expect(paths[0], 'foo'); + expect(paths[1], 'bar'); + final VerificationResult result = + verify(mockApi.showOpenDialog(captureAny, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect(options.allowMultiple, true); + expect(options.selectFolders, true); + }); + + test('passes initialDirectory correctly', () async { + await plugin.getDirectoryPath(initialDirectory: '/example/directory'); + + verify(mockApi.showOpenDialog(any, '/example/directory', null)); + }); + + test('passes confirmButtonText correctly', () async { + await plugin.getDirectoryPath(confirmButtonText: 'Open Directory'); + + verify(mockApi.showOpenDialog(any, null, 'Open Directory')); + }); + }); + + group('getSaveLocation', () { + setUp(() { + when(mockApi.showSaveDialog(any, any, any, any)) + .thenReturn(FileDialogResult(paths: ['foo'])); + }); + + test('simple call works', () async { + final FileSaveLocation? location = await plugin.getSaveLocation(); + + expect(location?.path, 'foo'); + expect(location?.activeFilter, null); + final VerificationResult result = + verify(mockApi.showSaveDialog(captureAny, null, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect(options.allowMultiple, false); + expect(options.selectFolders, false); + }); + + test('passes the accepted type groups correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + extensions: ['txt'], + mimeTypes: ['text/plain'], + ); + + const XTypeGroup groupTwo = XTypeGroup( + label: 'image', + extensions: ['jpg'], + mimeTypes: ['image/jpg'], + ); + + await plugin + .getSaveLocation(acceptedTypeGroups: [group, groupTwo]); + + final VerificationResult result = + verify(mockApi.showSaveDialog(captureAny, null, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect( + _typeGroupListsMatch(options.allowedTypes, [ + TypeGroup(label: 'text', extensions: ['txt']), + TypeGroup(label: 'image', extensions: ['jpg']), + ]), + true); + }); + + test('returns the selected type group correctly', () async { + when(mockApi.showSaveDialog(any, any, any, any)).thenReturn( + FileDialogResult(paths: ['foo'], typeGroupIndex: 1)); + const XTypeGroup group = XTypeGroup( + label: 'text', + extensions: ['txt'], + mimeTypes: ['text/plain'], + ); + + const XTypeGroup groupTwo = XTypeGroup( + label: 'image', + extensions: ['jpg'], + mimeTypes: ['image/jpg'], + ); + + final FileSaveLocation? result = await plugin + .getSaveLocation(acceptedTypeGroups: [group, groupTwo]); + + verify(mockApi.showSaveDialog(captureAny, null, null, null)); + + expect(result?.activeFilter, groupTwo); + }); + + test('passes initialDirectory correctly', () async { + await plugin.getSaveLocation( + options: + const SaveDialogOptions(initialDirectory: '/example/directory')); + + verify(mockApi.showSaveDialog(any, '/example/directory', null, null)); + }); + + test('passes suggestedName correctly', () async { + await plugin.getSaveLocation( + options: const SaveDialogOptions(suggestedName: 'baz.txt')); + + verify(mockApi.showSaveDialog(any, null, 'baz.txt', null)); + }); + + test('passes confirmButtonText correctly', () async { + await plugin.getSaveLocation( + options: const SaveDialogOptions(confirmButtonText: 'Save File')); + + verify(mockApi.showSaveDialog(any, null, null, 'Save File')); + }); + + test('throws for a type group that does not support Windows', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + mimeTypes: ['text/plain'], + ); + + await expectLater( + plugin.getSaveLocation(acceptedTypeGroups: [group]), + throwsArgumentError); + }); + + test('allows a wildcard group', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + ); + + await expectLater( + plugin.getSaveLocation(acceptedTypeGroups: [group]), + completes); + }); + }); + + group('getSavePath (deprecated)', () { + setUp(() { + when(mockApi.showSaveDialog(any, any, any, any)) + .thenReturn(FileDialogResult(paths: ['foo'])); + }); + + test('simple call works', () async { + final String? path = await plugin.getSavePath(); + + expect(path, 'foo'); + final VerificationResult result = + verify(mockApi.showSaveDialog(captureAny, null, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect(options.allowMultiple, false); + expect(options.selectFolders, false); + }); + + test('passes the accepted type groups correctly', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + extensions: ['txt'], + mimeTypes: ['text/plain'], + ); + + const XTypeGroup groupTwo = XTypeGroup( + label: 'image', + extensions: ['jpg'], + mimeTypes: ['image/jpg'], + ); + + await plugin + .getSavePath(acceptedTypeGroups: [group, groupTwo]); + + final VerificationResult result = + verify(mockApi.showSaveDialog(captureAny, null, null, null)); + final SelectionOptions options = result.captured[0] as SelectionOptions; + expect( + _typeGroupListsMatch(options.allowedTypes, [ + TypeGroup(label: 'text', extensions: ['txt']), + TypeGroup(label: 'image', extensions: ['jpg']), + ]), + true); + }); + + test('passes initialDirectory correctly', () async { + await plugin.getSavePath(initialDirectory: '/example/directory'); + + verify(mockApi.showSaveDialog(any, '/example/directory', null, null)); + }); + + test('passes suggestedName correctly', () async { + await plugin.getSavePath(suggestedName: 'baz.txt'); + + verify(mockApi.showSaveDialog(any, null, 'baz.txt', null)); + }); + + test('passes confirmButtonText correctly', () async { + await plugin.getSavePath(confirmButtonText: 'Save File'); + + verify(mockApi.showSaveDialog(any, null, null, 'Save File')); + }); + + test('throws for a type group that does not support Windows', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + mimeTypes: ['text/plain'], + ); + + await expectLater( + plugin.getSavePath(acceptedTypeGroups: [group]), + throwsArgumentError); + }); + + test('allows a wildcard group', () async { + const XTypeGroup group = XTypeGroup( + label: 'text', + ); + + await expectLater( + plugin.getSavePath(acceptedTypeGroups: [group]), + completes); + }); + }); +} + +// True if the given options match. +// +// This is needed because Pigeon data classes don't have custom equality checks, +// so only match for identical instances. +bool _typeGroupListsMatch(List a, List b) { + if (a.length != b.length) { + return false; + } + for (int i = 0; i < a.length; i++) { + if (!_typeGroupsMatch(a[i], b[i])) { + return false; + } + } + return true; +} + +// True if the given type groups match. +// +// This is needed because Pigeon data classes don't have custom equality checks, +// so only match for identical instances. +bool _typeGroupsMatch(TypeGroup? a, TypeGroup? b) { + return a!.label == b!.label && listEquals(a.extensions, b.extensions); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/test/file_selector_windows_test.mocks.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/test/file_selector_windows_test.mocks.dart new file mode 100755 index 00000000..e673ab00 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/test/file_selector_windows_test.mocks.dart @@ -0,0 +1,102 @@ +// Mocks generated by Mockito 5.4.4 from annotations +// in file_selector_windows/test/file_selector_windows_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:file_selector_windows/src/messages.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; + +import 'test_api.g.dart' as _i3; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +class _FakeFileDialogResult_0 extends _i1.SmartFake + implements _i2.FileDialogResult { + _FakeFileDialogResult_0( + Object parent, + Invocation parentInvocation, + ) : super( + parent, + parentInvocation, + ); +} + +/// A class which mocks [TestFileSelectorApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTestFileSelectorApi extends _i1.Mock + implements _i3.TestFileSelectorApi { + MockTestFileSelectorApi() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.FileDialogResult showOpenDialog( + _i2.SelectionOptions? options, + String? initialDirectory, + String? confirmButtonText, + ) => + (super.noSuchMethod( + Invocation.method( + #showOpenDialog, + [ + options, + initialDirectory, + confirmButtonText, + ], + ), + returnValue: _FakeFileDialogResult_0( + this, + Invocation.method( + #showOpenDialog, + [ + options, + initialDirectory, + confirmButtonText, + ], + ), + ), + ) as _i2.FileDialogResult); + + @override + _i2.FileDialogResult showSaveDialog( + _i2.SelectionOptions? options, + String? initialDirectory, + String? suggestedName, + String? confirmButtonText, + ) => + (super.noSuchMethod( + Invocation.method( + #showSaveDialog, + [ + options, + initialDirectory, + suggestedName, + confirmButtonText, + ], + ), + returnValue: _FakeFileDialogResult_0( + this, + Invocation.method( + #showSaveDialog, + [ + options, + initialDirectory, + suggestedName, + confirmButtonText, + ], + ), + ), + ) as _i2.FileDialogResult); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/CMakeLists.txt new file mode 100755 index 00000000..906821c1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/CMakeLists.txt @@ -0,0 +1,88 @@ +cmake_minimum_required(VERSION 3.14) +set(PROJECT_NAME "file_selector_windows") +project(${PROJECT_NAME} LANGUAGES CXX) + +cmake_policy(VERSION 3.14...3.24) + +set(PLUGIN_NAME "${PROJECT_NAME}_plugin") + +list(APPEND PLUGIN_SOURCES + "file_dialog_controller.cpp" + "file_dialog_controller.h" + "file_selector_plugin.cpp" + "file_selector_plugin.h" + "messages.g.cpp" + "messages.g.h" + "string_utils.cpp" + "string_utils.h" +) + +add_library(${PLUGIN_NAME} SHARED + "file_selector_windows.cpp" + "include/file_selector_windows/file_selector_windows.h" + ${PLUGIN_SOURCES} +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) +# Override apply_standard_settings for exceptions due to +# https://developercommunity.visualstudio.com/t/stdany-doesnt-link-when-exceptions-are-disabled/376072 +target_compile_definitions(${PLUGIN_NAME} PRIVATE "_HAS_EXCEPTIONS=1") + +# List of absolute paths to libraries that should be bundled with the plugin +set(file_selector_bundled_libraries + "" + PARENT_SCOPE +) + + +# === Tests === + +if (${include_${PROJECT_NAME}_tests}) +set(TEST_RUNNER "${PROJECT_NAME}_test") +enable_testing() +# TODO(stuartmorgan): Consider using a single shared, pre-checked-in googletest +# instance rather than downloading for each plugin. This approach makes sense +# for a template, but not for a monorepo with many plugins. +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/release-1.11.0.zip +) +# Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Disable install commands for gtest so it doesn't end up in the bundle. +set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE) + +FetchContent_MakeAvailable(googletest) + +# The plugin's C API is not very useful for unit testing, so build the sources +# directly into the test binary rather than using the DLL. +add_executable(${TEST_RUNNER} + test/file_selector_plugin_test.cpp + test/test_main.cpp + test/test_file_dialog_controller.cpp + test/test_file_dialog_controller.h + test/test_utils.cpp + test/test_utils.h + ${PLUGIN_SOURCES} +) +apply_standard_settings(${TEST_RUNNER}) +target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") +target_link_libraries(${TEST_RUNNER} PRIVATE flutter_wrapper_plugin) +target_link_libraries(${TEST_RUNNER} PRIVATE gtest gmock) +# Override apply_standard_settings for exceptions due to +# https://developercommunity.visualstudio.com/t/stdany-doesnt-link-when-exceptions-are-disabled/376072 +target_compile_definitions(${TEST_RUNNER} PRIVATE "_HAS_EXCEPTIONS=1") +# flutter_wrapper_plugin has link dependencies on the Flutter DLL. +add_custom_command(TARGET ${TEST_RUNNER} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${FLUTTER_LIBRARY}" $ +) + +include(GoogleTest) +gtest_discover_tests(${TEST_RUNNER}) +endif() diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_dialog_controller.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_dialog_controller.cpp new file mode 100755 index 00000000..af2a9aff --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_dialog_controller.cpp @@ -0,0 +1,70 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "file_dialog_controller.h" + +#include +#include +#include + +_COM_SMARTPTR_TYPEDEF(IFileOpenDialog, IID_IFileOpenDialog); + +namespace file_selector_windows { + +FileDialogController::FileDialogController(IFileDialog* dialog) + : dialog_(dialog) {} + +FileDialogController::~FileDialogController() {} + +HRESULT FileDialogController::SetFolder(IShellItem* folder) { + return dialog_->SetFolder(folder); +} + +HRESULT FileDialogController::SetFileName(const wchar_t* name) { + return dialog_->SetFileName(name); +} + +HRESULT FileDialogController::SetFileTypes(UINT count, + COMDLG_FILTERSPEC* filters) { + return dialog_->SetFileTypes(count, filters); +} + +HRESULT FileDialogController::SetOkButtonLabel(const wchar_t* text) { + return dialog_->SetOkButtonLabel(text); +} + +HRESULT FileDialogController::GetOptions( + FILEOPENDIALOGOPTIONS* out_options) const { + return dialog_->GetOptions(out_options); +} + +HRESULT FileDialogController::SetOptions(FILEOPENDIALOGOPTIONS options) { + return dialog_->SetOptions(options); +} + +HRESULT FileDialogController::Show(HWND parent) { + return dialog_->Show(parent); +} + +HRESULT FileDialogController::GetResult(IShellItem** out_item) const { + return dialog_->GetResult(out_item); +} + +HRESULT FileDialogController::GetFileTypeIndex(UINT* out_index) const { + return dialog_->GetFileTypeIndex(out_index); +} + +HRESULT FileDialogController::GetResults(IShellItemArray** out_items) const { + IFileOpenDialogPtr open_dialog; + HRESULT result = dialog_->QueryInterface(IID_PPV_ARGS(&open_dialog)); + if (!SUCCEEDED(result)) { + return result; + } + result = open_dialog->GetResults(out_items); + return result; +} + +FileDialogControllerFactory::~FileDialogControllerFactory() {} + +} // namespace file_selector_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_dialog_controller.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_dialog_controller.h new file mode 100755 index 00000000..ab492928 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_dialog_controller.h @@ -0,0 +1,63 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_FILE_DIALOG_CONTROLLER_H_ +#define PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_FILE_DIALOG_CONTROLLER_H_ + +#include +#include +#include +#include + +#include + +_COM_SMARTPTR_TYPEDEF(IFileDialog, IID_IFileDialog); + +namespace file_selector_windows { + +// A thin wrapper for IFileDialog to allow for faking and inspection in tests. +// +// Since this class defines the end of what can be unit tested, it should +// contain as little logic as possible. +class FileDialogController { + public: + // Creates a controller managing |dialog|. + FileDialogController(IFileDialog* dialog); + virtual ~FileDialogController(); + + // Disallow copy and assign. + FileDialogController(const FileDialogController&) = delete; + FileDialogController& operator=(const FileDialogController&) = delete; + + // IFileDialog wrappers: + virtual HRESULT SetFolder(IShellItem* folder); + virtual HRESULT SetFileName(const wchar_t* name); + virtual HRESULT SetFileTypes(UINT count, COMDLG_FILTERSPEC* filters); + virtual HRESULT SetOkButtonLabel(const wchar_t* text); + virtual HRESULT GetOptions(FILEOPENDIALOGOPTIONS* out_options) const; + virtual HRESULT SetOptions(FILEOPENDIALOGOPTIONS options); + virtual HRESULT Show(HWND parent); + virtual HRESULT GetResult(IShellItem** out_item) const; + virtual HRESULT GetFileTypeIndex(UINT* out_index) const; + + // IFileOpenDialog wrapper. This will fail if the IFileDialog* provided to the + // constructor was not an IFileOpenDialog instance. + virtual HRESULT GetResults(IShellItemArray** out_items) const; + + private: + IFileDialogPtr dialog_ = nullptr; +}; + +// Interface for creating FileDialogControllers, to allow for dependency +// injection. +class FileDialogControllerFactory { + public: + virtual ~FileDialogControllerFactory(); + + virtual std::unique_ptr CreateController( + IFileDialog* dialog) const = 0; +}; + +} // namespace file_selector_windows + +#endif // PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_FILE_DIALOG_CONTROLLER_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_selector_plugin.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_selector_plugin.cpp new file mode 100755 index 00000000..3a43bd15 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_selector_plugin.cpp @@ -0,0 +1,309 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "file_selector_plugin.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "file_dialog_controller.h" +#include "string_utils.h" + +_COM_SMARTPTR_TYPEDEF(IEnumShellItems, IID_IEnumShellItems); +_COM_SMARTPTR_TYPEDEF(IFileDialog, IID_IFileDialog); +_COM_SMARTPTR_TYPEDEF(IShellItem, IID_IShellItem); +_COM_SMARTPTR_TYPEDEF(IShellItemArray, IID_IShellItemArray); + +namespace file_selector_windows { + +namespace { + +using flutter::CustomEncodableValue; +using flutter::EncodableList; +using flutter::EncodableValue; + +// The kind of file dialog to show. +enum class DialogMode { open, save }; + +// Returns the path for |shell_item| as a UTF-8 string, or an +// empty string on failure. +std::string GetPathForShellItem(IShellItem* shell_item) { + if (shell_item == nullptr) { + return ""; + } + wchar_t* wide_path = nullptr; + if (!SUCCEEDED(shell_item->GetDisplayName(SIGDN_FILESYSPATH, &wide_path))) { + return ""; + } + std::string path = Utf8FromUtf16(wide_path); + ::CoTaskMemFree(wide_path); + return path; +} + +// Implementation of FileDialogControllerFactory that makes standard +// FileDialogController instances. +class DefaultFileDialogControllerFactory : public FileDialogControllerFactory { + public: + DefaultFileDialogControllerFactory() {} + virtual ~DefaultFileDialogControllerFactory() {} + + // Disallow copy and assign. + DefaultFileDialogControllerFactory( + const DefaultFileDialogControllerFactory&) = delete; + DefaultFileDialogControllerFactory& operator=( + const DefaultFileDialogControllerFactory&) = delete; + + std::unique_ptr CreateController( + IFileDialog* dialog) const override { + assert(dialog != nullptr); + return std::make_unique(dialog); + } +}; + +// Wraps an IFileDialog, managing object lifetime as a scoped object and +// providing a simplified API for interacting with it as needed for the plugin. +class DialogWrapper { + public: + explicit DialogWrapper(const FileDialogControllerFactory& dialog_factory, + IID type) { + is_open_dialog_ = type == CLSID_FileOpenDialog; + IFileDialogPtr dialog = nullptr; + last_result_ = CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&dialog)); + dialog_controller_ = dialog_factory.CreateController(dialog); + } + + // Attempts to set the default folder for the dialog to |path|, + // if it exists. + void SetFolder(std::string_view path) { + std::wstring wide_path = Utf16FromUtf8(path); + IShellItemPtr item; + last_result_ = SHCreateItemFromParsingName(wide_path.c_str(), nullptr, + IID_PPV_ARGS(&item)); + if (!SUCCEEDED(last_result_)) { + return; + } + dialog_controller_->SetFolder(item); + } + + // Sets the file name that is initially shown in the dialog. + void SetFileName(std::string_view name) { + std::wstring wide_name = Utf16FromUtf8(name); + last_result_ = dialog_controller_->SetFileName(wide_name.c_str()); + } + + // Sets the label of the confirmation button. + void SetOkButtonLabel(std::string_view label) { + std::wstring wide_label = Utf16FromUtf8(label); + last_result_ = dialog_controller_->SetOkButtonLabel(wide_label.c_str()); + } + + // Adds the given options to the dialog's current option set. + void AddOptions(FILEOPENDIALOGOPTIONS new_options) { + FILEOPENDIALOGOPTIONS options; + last_result_ = dialog_controller_->GetOptions(&options); + if (!SUCCEEDED(last_result_)) { + return; + } + options |= new_options; + if (options & FOS_PICKFOLDERS) { + opening_directory_ = true; + } + last_result_ = dialog_controller_->SetOptions(options); + } + + // Sets the filters for allowed file types to select. + void SetFileTypeFilters(const EncodableList& filters) { + const std::wstring spec_delimiter = L";"; + const std::wstring file_wildcard = L"*."; + std::vector filter_specs; + // Temporary ownership of the constructed strings whose data is used in + // filter_specs, so that they live until the call to SetFileTypes is done. + std::vector filter_names; + std::vector filter_extensions; + filter_extensions.reserve(filters.size()); + filter_names.reserve(filters.size()); + + for (const EncodableValue& filter_info_value : filters) { + const auto& type_group = std::any_cast( + std::get(filter_info_value)); + filter_names.push_back(Utf16FromUtf8(type_group.label())); + filter_extensions.push_back(L""); + std::wstring& spec = filter_extensions.back(); + if (type_group.extensions().empty()) { + spec += L"*.*"; + } else { + for (const EncodableValue& extension : type_group.extensions()) { + if (!spec.empty()) { + spec += spec_delimiter; + } + spec += + file_wildcard + Utf16FromUtf8(std::get(extension)); + } + } + filter_specs.push_back({filter_names.back().c_str(), spec.c_str()}); + } + last_result_ = dialog_controller_->SetFileTypes( + static_cast(filter_specs.size()), filter_specs.data()); + } + + // Displays the dialog, and returns the result, or nullopt on error. + std::optional Show(HWND parent_window) { + assert(dialog_controller_); + last_result_ = dialog_controller_->Show(parent_window); + if (!SUCCEEDED(last_result_)) { + return std::nullopt; + } + + EncodableList files; + if (is_open_dialog_) { + IShellItemArrayPtr shell_items; + last_result_ = dialog_controller_->GetResults(&shell_items); + if (!SUCCEEDED(last_result_)) { + return std::nullopt; + } + IEnumShellItemsPtr item_enumerator; + last_result_ = shell_items->EnumItems(&item_enumerator); + if (!SUCCEEDED(last_result_)) { + return std::nullopt; + } + IShellItemPtr shell_item; + while (item_enumerator->Next(1, &shell_item, nullptr) == S_OK) { + files.push_back(EncodableValue(GetPathForShellItem(shell_item))); + } + } else { + IShellItemPtr shell_item; + last_result_ = dialog_controller_->GetResult(&shell_item); + if (!SUCCEEDED(last_result_)) { + return std::nullopt; + } + files.push_back(EncodableValue(GetPathForShellItem(shell_item))); + } + FileDialogResult result(files, nullptr); + UINT file_type_index; + if (SUCCEEDED(dialog_controller_->GetFileTypeIndex(&file_type_index)) && + file_type_index > 0) { + // Convert from the one-based index to a Dart index. + result.set_type_group_index(file_type_index - 1); + } + return result; + } + + // Returns the result of the last Win32 API call related to this object. + HRESULT last_result() { return last_result_; } + + private: + // The dialog controller that all interactions are mediated through, to allow + // for unit testing. + std::unique_ptr dialog_controller_; + bool is_open_dialog_; + bool opening_directory_ = false; + HRESULT last_result_; +}; + +ErrorOr ShowDialog( + const FileDialogControllerFactory& dialog_factory, HWND parent_window, + DialogMode mode, const SelectionOptions& options, + const std::string* initial_directory, const std::string* suggested_name, + const std::string* confirm_label) { + IID dialog_type = + mode == DialogMode::save ? CLSID_FileSaveDialog : CLSID_FileOpenDialog; + DialogWrapper dialog(dialog_factory, dialog_type); + if (!SUCCEEDED(dialog.last_result())) { + return FlutterError( + "System error", "Could not create dialog", + EncodableValue(std::in_place_type, dialog.last_result())); + } + + FILEOPENDIALOGOPTIONS dialog_options = 0; + if (options.select_folders()) { + dialog_options |= FOS_PICKFOLDERS; + } + if (options.allow_multiple()) { + dialog_options |= FOS_ALLOWMULTISELECT; + } + if (dialog_options != 0) { + dialog.AddOptions(dialog_options); + } + + if (initial_directory) { + dialog.SetFolder(*initial_directory); + } + if (suggested_name) { + dialog.SetFileName(*suggested_name); + } + if (confirm_label) { + dialog.SetOkButtonLabel(*confirm_label); + } + + if (!options.allowed_types().empty()) { + dialog.SetFileTypeFilters(options.allowed_types()); + } + + std::optional result = dialog.Show(parent_window); + if (!result) { + if (dialog.last_result() != HRESULT_FROM_WIN32(ERROR_CANCELLED)) { + return FlutterError( + "System error", "Could not show dialog", + EncodableValue(std::in_place_type, dialog.last_result())); + } else { + return FileDialogResult(EncodableList(), nullptr); + } + } + return std::move(result.value()); +} + +// Returns the top-level window that owns |view|. +HWND GetRootWindow(flutter::FlutterView* view) { + return ::GetAncestor(view->GetNativeWindow(), GA_ROOT); +} + +} // namespace + +// static +void FileSelectorPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarWindows* registrar) { + std::unique_ptr plugin = + std::make_unique( + [registrar] { return GetRootWindow(registrar->GetView()); }, + std::make_unique()); + + FileSelectorApi::SetUp(registrar->messenger(), plugin.get()); + registrar->AddPlugin(std::move(plugin)); +} + +FileSelectorPlugin::FileSelectorPlugin( + FlutterRootWindowProvider window_provider, + std::unique_ptr dialog_controller_factory) + : get_root_window_(std::move(window_provider)), + controller_factory_(std::move(dialog_controller_factory)) {} + +FileSelectorPlugin::~FileSelectorPlugin() = default; + +ErrorOr FileSelectorPlugin::ShowOpenDialog( + const SelectionOptions& options, const std::string* initialDirectory, + const std::string* confirmButtonText) { + return ShowDialog(*controller_factory_, get_root_window_(), DialogMode::open, + options, initialDirectory, nullptr, confirmButtonText); +} + +ErrorOr FileSelectorPlugin::ShowSaveDialog( + const SelectionOptions& options, const std::string* initialDirectory, + const std::string* suggestedName, const std::string* confirmButtonText) { + return ShowDialog(*controller_factory_, get_root_window_(), DialogMode::save, + options, initialDirectory, suggestedName, + confirmButtonText); +} + +} // namespace file_selector_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_selector_plugin.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_selector_plugin.h new file mode 100755 index 00000000..2f17f949 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_selector_plugin.h @@ -0,0 +1,53 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_FILE_SELECTOR_PLUGIN_H_ +#define PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_FILE_SELECTOR_PLUGIN_H_ + +#include +#include + +#include + +#include "file_dialog_controller.h" +#include "messages.g.h" + +namespace file_selector_windows { + +// Abstraction for accessing the Flutter view's root window, to allow for faking +// in unit tests without creating fake window hierarchies, as well as to work +// around https://github.com/flutter/flutter/issues/90694. +using FlutterRootWindowProvider = std::function; + +class FileSelectorPlugin : public flutter::Plugin, public FileSelectorApi { + public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar); + + // Creates a new plugin instance for the given registar, using the given + // factory to create native dialog controllers. + FileSelectorPlugin( + FlutterRootWindowProvider window_provider, + std::unique_ptr dialog_controller_factory); + + virtual ~FileSelectorPlugin(); + + // FileSelectorApi + ErrorOr ShowOpenDialog( + const SelectionOptions& options, const std::string* initial_directory, + const std::string* confirm_button_text) override; + ErrorOr ShowSaveDialog( + const SelectionOptions& options, const std::string* initialDirectory, + const std::string* suggestedName, + const std::string* confirmButtonText) override; + + private: + // The provider for the root window to attach the dialog to. + FlutterRootWindowProvider get_root_window_; + + // The factory for creating dialog controller instances. + std::unique_ptr controller_factory_; +}; + +} // namespace file_selector_windows + +#endif // PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_FILE_SELECTOR_PLUGIN_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_selector_windows.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_selector_windows.cpp new file mode 100755 index 00000000..e4d2c15f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/file_selector_windows.cpp @@ -0,0 +1,15 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "include/file_selector_windows/file_selector_windows.h" + +#include + +#include "file_selector_plugin.h" + +void FileSelectorWindowsRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + file_selector_windows::FileSelectorPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/include/file_selector_windows/file_selector_windows.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/include/file_selector_windows/file_selector_windows.h new file mode 100755 index 00000000..7ee6ed3d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/include/file_selector_windows/file_selector_windows.h @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_INCLUDE_FILE_SELECTOR_WINDOWS_FILE_SELECTOR_WINDOWS_H_ +#define PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_INCLUDE_FILE_SELECTOR_WINDOWS_FILE_SELECTOR_WINDOWS_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void FileSelectorWindowsRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_INCLUDE_FILE_SELECTOR_WINDOWS_FILE_SELECTOR_WINDOWS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/messages.g.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/messages.g.cpp new file mode 100755 index 00000000..f831e50e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/messages.g.cpp @@ -0,0 +1,334 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v22.4.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#undef _HAS_EXCEPTIONS + +#include "messages.g.h" + +#include +#include +#include +#include + +#include +#include +#include + +namespace file_selector_windows { +using flutter::BasicMessageChannel; +using flutter::CustomEncodableValue; +using flutter::EncodableList; +using flutter::EncodableMap; +using flutter::EncodableValue; + +FlutterError CreateConnectionError(const std::string channel_name) { + return FlutterError( + "channel-error", + "Unable to establish connection on channel: '" + channel_name + "'.", + EncodableValue("")); +} + +// TypeGroup + +TypeGroup::TypeGroup(const std::string& label, const EncodableList& extensions) + : label_(label), extensions_(extensions) {} + +const std::string& TypeGroup::label() const { return label_; } + +void TypeGroup::set_label(std::string_view value_arg) { label_ = value_arg; } + +const EncodableList& TypeGroup::extensions() const { return extensions_; } + +void TypeGroup::set_extensions(const EncodableList& value_arg) { + extensions_ = value_arg; +} + +EncodableList TypeGroup::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(label_)); + list.push_back(EncodableValue(extensions_)); + return list; +} + +TypeGroup TypeGroup::FromEncodableList(const EncodableList& list) { + TypeGroup decoded(std::get(list[0]), + std::get(list[1])); + return decoded; +} + +// SelectionOptions + +SelectionOptions::SelectionOptions(bool allow_multiple, bool select_folders, + const EncodableList& allowed_types) + : allow_multiple_(allow_multiple), + select_folders_(select_folders), + allowed_types_(allowed_types) {} + +bool SelectionOptions::allow_multiple() const { return allow_multiple_; } + +void SelectionOptions::set_allow_multiple(bool value_arg) { + allow_multiple_ = value_arg; +} + +bool SelectionOptions::select_folders() const { return select_folders_; } + +void SelectionOptions::set_select_folders(bool value_arg) { + select_folders_ = value_arg; +} + +const EncodableList& SelectionOptions::allowed_types() const { + return allowed_types_; +} + +void SelectionOptions::set_allowed_types(const EncodableList& value_arg) { + allowed_types_ = value_arg; +} + +EncodableList SelectionOptions::ToEncodableList() const { + EncodableList list; + list.reserve(3); + list.push_back(EncodableValue(allow_multiple_)); + list.push_back(EncodableValue(select_folders_)); + list.push_back(EncodableValue(allowed_types_)); + return list; +} + +SelectionOptions SelectionOptions::FromEncodableList( + const EncodableList& list) { + SelectionOptions decoded(std::get(list[0]), std::get(list[1]), + std::get(list[2])); + return decoded; +} + +// FileDialogResult + +FileDialogResult::FileDialogResult(const EncodableList& paths) + : paths_(paths) {} + +FileDialogResult::FileDialogResult(const EncodableList& paths, + const int64_t* type_group_index) + : paths_(paths), + type_group_index_(type_group_index + ? std::optional(*type_group_index) + : std::nullopt) {} + +const EncodableList& FileDialogResult::paths() const { return paths_; } + +void FileDialogResult::set_paths(const EncodableList& value_arg) { + paths_ = value_arg; +} + +const int64_t* FileDialogResult::type_group_index() const { + return type_group_index_ ? &(*type_group_index_) : nullptr; +} + +void FileDialogResult::set_type_group_index(const int64_t* value_arg) { + type_group_index_ = + value_arg ? std::optional(*value_arg) : std::nullopt; +} + +void FileDialogResult::set_type_group_index(int64_t value_arg) { + type_group_index_ = value_arg; +} + +EncodableList FileDialogResult::ToEncodableList() const { + EncodableList list; + list.reserve(2); + list.push_back(EncodableValue(paths_)); + list.push_back(type_group_index_ ? EncodableValue(*type_group_index_) + : EncodableValue()); + return list; +} + +FileDialogResult FileDialogResult::FromEncodableList( + const EncodableList& list) { + FileDialogResult decoded(std::get(list[0])); + auto& encodable_type_group_index = list[1]; + if (!encodable_type_group_index.IsNull()) { + decoded.set_type_group_index(std::get(encodable_type_group_index)); + } + return decoded; +} + +PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} + +EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( + uint8_t type, flutter::ByteStreamReader* stream) const { + switch (type) { + case 129: { + return CustomEncodableValue(TypeGroup::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 130: { + return CustomEncodableValue(SelectionOptions::FromEncodableList( + std::get(ReadValue(stream)))); + } + case 131: { + return CustomEncodableValue(FileDialogResult::FromEncodableList( + std::get(ReadValue(stream)))); + } + default: + return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); + } +} + +void PigeonInternalCodecSerializer::WriteValue( + const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + if (const CustomEncodableValue* custom_value = + std::get_if(&value)) { + if (custom_value->type() == typeid(TypeGroup)) { + stream->WriteByte(129); + WriteValue(EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(SelectionOptions)) { + stream->WriteByte(130); + WriteValue( + EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); + return; + } + if (custom_value->type() == typeid(FileDialogResult)) { + stream->WriteByte(131); + WriteValue( + EncodableValue( + std::any_cast(*custom_value).ToEncodableList()), + stream); + return; + } + } + flutter::StandardCodecSerializer::WriteValue(value, stream); +} + +/// The codec used by FileSelectorApi. +const flutter::StandardMessageCodec& FileSelectorApi::GetCodec() { + return flutter::StandardMessageCodec::GetInstance( + &PigeonInternalCodecSerializer::GetInstance()); +} + +// Sets up an instance of `FileSelectorApi` to handle messages through the +// `binary_messenger`. +void FileSelectorApi::SetUp(flutter::BinaryMessenger* binary_messenger, + FileSelectorApi* api) { + FileSelectorApi::SetUp(binary_messenger, api, ""); +} + +void FileSelectorApi::SetUp(flutter::BinaryMessenger* binary_messenger, + FileSelectorApi* api, + const std::string& message_channel_suffix) { + const std::string prepended_suffix = + message_channel_suffix.length() > 0 + ? std::string(".") + message_channel_suffix + : ""; + { + BasicMessageChannel<> channel(binary_messenger, + "dev.flutter.pigeon.file_selector_windows." + "FileSelectorApi.showOpenDialog" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_options_arg = args.at(0); + if (encodable_options_arg.IsNull()) { + reply(WrapError("options_arg unexpectedly null.")); + return; + } + const auto& options_arg = std::any_cast( + std::get(encodable_options_arg)); + const auto& encodable_initial_directory_arg = args.at(1); + const auto* initial_directory_arg = + std::get_if(&encodable_initial_directory_arg); + const auto& encodable_confirm_button_text_arg = args.at(2); + const auto* confirm_button_text_arg = + std::get_if(&encodable_confirm_button_text_arg); + ErrorOr output = api->ShowOpenDialog( + options_arg, initial_directory_arg, confirm_button_text_arg); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel(binary_messenger, + "dev.flutter.pigeon.file_selector_windows." + "FileSelectorApi.showSaveDialog" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_options_arg = args.at(0); + if (encodable_options_arg.IsNull()) { + reply(WrapError("options_arg unexpectedly null.")); + return; + } + const auto& options_arg = std::any_cast( + std::get(encodable_options_arg)); + const auto& encodable_initial_directory_arg = args.at(1); + const auto* initial_directory_arg = + std::get_if(&encodable_initial_directory_arg); + const auto& encodable_suggested_name_arg = args.at(2); + const auto* suggested_name_arg = + std::get_if(&encodable_suggested_name_arg); + const auto& encodable_confirm_button_text_arg = args.at(3); + const auto* confirm_button_text_arg = + std::get_if(&encodable_confirm_button_text_arg); + ErrorOr output = api->ShowSaveDialog( + options_arg, initial_directory_arg, suggested_name_arg, + confirm_button_text_arg); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back( + CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } +} + +EncodableValue FileSelectorApi::WrapError(std::string_view error_message) { + return EncodableValue( + EncodableList{EncodableValue(std::string(error_message)), + EncodableValue("Error"), EncodableValue()}); +} + +EncodableValue FileSelectorApi::WrapError(const FlutterError& error) { + return EncodableValue(EncodableList{EncodableValue(error.code()), + EncodableValue(error.message()), + error.details()}); +} + +} // namespace file_selector_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/messages.g.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/messages.g.h new file mode 100755 index 00000000..edd0865d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/messages.g.h @@ -0,0 +1,191 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v22.4.1), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#ifndef PIGEON_MESSAGES_G_H_ +#define PIGEON_MESSAGES_G_H_ +#include +#include +#include +#include + +#include +#include +#include + +namespace file_selector_windows { + +// Generated class from Pigeon. + +class FlutterError { + public: + explicit FlutterError(const std::string& code) : code_(code) {} + explicit FlutterError(const std::string& code, const std::string& message) + : code_(code), message_(message) {} + explicit FlutterError(const std::string& code, const std::string& message, + const flutter::EncodableValue& details) + : code_(code), message_(message), details_(details) {} + + const std::string& code() const { return code_; } + const std::string& message() const { return message_; } + const flutter::EncodableValue& details() const { return details_; } + + private: + std::string code_; + std::string message_; + flutter::EncodableValue details_; +}; + +template +class ErrorOr { + public: + ErrorOr(const T& rhs) : v_(rhs) {} + ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} + ErrorOr(const FlutterError& rhs) : v_(rhs) {} + ErrorOr(const FlutterError&& rhs) : v_(std::move(rhs)) {} + + bool has_error() const { return std::holds_alternative(v_); } + const T& value() const { return std::get(v_); }; + const FlutterError& error() const { return std::get(v_); }; + + private: + friend class FileSelectorApi; + ErrorOr() = default; + T TakeValue() && { return std::get(std::move(v_)); } + + std::variant v_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class TypeGroup { + public: + // Constructs an object setting all fields. + explicit TypeGroup(const std::string& label, + const flutter::EncodableList& extensions); + + const std::string& label() const; + void set_label(std::string_view value_arg); + + const flutter::EncodableList& extensions() const; + void set_extensions(const flutter::EncodableList& value_arg); + + private: + static TypeGroup FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FileSelectorApi; + friend class PigeonInternalCodecSerializer; + std::string label_; + flutter::EncodableList extensions_; +}; + +// Generated class from Pigeon that represents data sent in messages. +class SelectionOptions { + public: + // Constructs an object setting all fields. + explicit SelectionOptions(bool allow_multiple, bool select_folders, + const flutter::EncodableList& allowed_types); + + bool allow_multiple() const; + void set_allow_multiple(bool value_arg); + + bool select_folders() const; + void set_select_folders(bool value_arg); + + const flutter::EncodableList& allowed_types() const; + void set_allowed_types(const flutter::EncodableList& value_arg); + + private: + static SelectionOptions FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FileSelectorApi; + friend class PigeonInternalCodecSerializer; + bool allow_multiple_; + bool select_folders_; + flutter::EncodableList allowed_types_; +}; + +// The result from an open or save dialog. +// +// Generated class from Pigeon that represents data sent in messages. +class FileDialogResult { + public: + // Constructs an object setting all non-nullable fields. + explicit FileDialogResult(const flutter::EncodableList& paths); + + // Constructs an object setting all fields. + explicit FileDialogResult(const flutter::EncodableList& paths, + const int64_t* type_group_index); + + // The selected paths. + // + // Empty if the dialog was canceled. + const flutter::EncodableList& paths() const; + void set_paths(const flutter::EncodableList& value_arg); + + // The type group index (into the list provided in [SelectionOptions]) of + // the group that was selected when the dialog was confirmed. + // + // Null if no type groups were provided, or the dialog was canceled. + const int64_t* type_group_index() const; + void set_type_group_index(const int64_t* value_arg); + void set_type_group_index(int64_t value_arg); + + private: + static FileDialogResult FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class FileSelectorApi; + friend class PigeonInternalCodecSerializer; + flutter::EncodableList paths_; + std::optional type_group_index_; +}; + +class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { + public: + PigeonInternalCodecSerializer(); + inline static PigeonInternalCodecSerializer& GetInstance() { + static PigeonInternalCodecSerializer sInstance; + return sInstance; + } + + void WriteValue(const flutter::EncodableValue& value, + flutter::ByteStreamWriter* stream) const override; + + protected: + flutter::EncodableValue ReadValueOfType( + uint8_t type, flutter::ByteStreamReader* stream) const override; +}; + +// Generated interface from Pigeon that represents a handler of messages from +// Flutter. +class FileSelectorApi { + public: + FileSelectorApi(const FileSelectorApi&) = delete; + FileSelectorApi& operator=(const FileSelectorApi&) = delete; + virtual ~FileSelectorApi() {} + virtual ErrorOr ShowOpenDialog( + const SelectionOptions& options, const std::string* initial_directory, + const std::string* confirm_button_text) = 0; + virtual ErrorOr ShowSaveDialog( + const SelectionOptions& options, const std::string* initial_directory, + const std::string* suggested_name, + const std::string* confirm_button_text) = 0; + + // The codec used by FileSelectorApi. + static const flutter::StandardMessageCodec& GetCodec(); + // Sets up an instance of `FileSelectorApi` to handle messages through the + // `binary_messenger`. + static void SetUp(flutter::BinaryMessenger* binary_messenger, + FileSelectorApi* api); + static void SetUp(flutter::BinaryMessenger* binary_messenger, + FileSelectorApi* api, + const std::string& message_channel_suffix); + static flutter::EncodableValue WrapError(std::string_view error_message); + static flutter::EncodableValue WrapError(const FlutterError& error); + + protected: + FileSelectorApi() = default; +}; +} // namespace file_selector_windows +#endif // PIGEON_MESSAGES_G_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/string_utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/string_utils.cpp new file mode 100755 index 00000000..6fa7c184 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/string_utils.cpp @@ -0,0 +1,60 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "string_utils.h" + +#include +#include + +#include + +namespace file_selector_windows { + +// Converts the given UTF-16 string to UTF-8. +std::string Utf8FromUtf16(std::wstring_view utf16_string) { + if (utf16_string.empty()) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string.data(), + static_cast(utf16_string.length()), nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string.data(), + static_cast(utf16_string.length()), utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} + +// Converts the given UTF-8 string to UTF-16. +std::wstring Utf16FromUtf8(std::string_view utf8_string) { + if (utf8_string.empty()) { + return std::wstring(); + } + int target_length = + ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(), + static_cast(utf8_string.length()), nullptr, 0); + if (target_length == 0) { + return std::wstring(); + } + std::wstring utf16_string; + utf16_string.resize(target_length); + int converted_length = + ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(), + static_cast(utf8_string.length()), + utf16_string.data(), target_length); + if (converted_length == 0) { + return std::wstring(); + } + return utf16_string; +} + +} // namespace file_selector_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/string_utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/string_utils.h new file mode 100755 index 00000000..2323a5a5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/string_utils.h @@ -0,0 +1,21 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_STRING_UTILS_H_ +#define PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_STRING_UTILS_H_ + +#include + +#include + +namespace file_selector_windows { + +// Converts the given UTF-16 string to UTF-8. +std::string Utf8FromUtf16(std::wstring_view utf16_string); + +// Converts the given UTF-8 string to UTF-16. +std::wstring Utf16FromUtf8(std::string_view utf8_string); + +} // namespace file_selector_windows + +#endif // PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_STRING_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/file_selector_plugin_test.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/file_selector_plugin_test.cpp new file mode 100755 index 00000000..ee6d4dcd --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/file_selector_plugin_test.cpp @@ -0,0 +1,544 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "file_selector_plugin.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "file_dialog_controller.h" +#include "string_utils.h" +#include "test/test_file_dialog_controller.h" +#include "test/test_utils.h" + +namespace file_selector_windows { +namespace test { + +namespace { + +using flutter::CustomEncodableValue; +using flutter::EncodableList; +using flutter::EncodableValue; + +} // namespace + +TEST(FileSelectorPlugin, TestOpenSimple) { + const HWND fake_window = reinterpret_cast(1337); + ScopedTestShellItem fake_selected_file; + IShellItemArrayPtr fake_result_array; + ::SHCreateShellItemArrayFromShellItem(fake_selected_file.file(), + IID_PPV_ARGS(&fake_result_array)); + + bool shown = false; + MockShow show_validator = [&shown, fake_result_array, fake_window]( + const TestFileDialogController& dialog, + HWND parent) { + shown = true; + EXPECT_EQ(parent, fake_window); + + // Validate options. + FILEOPENDIALOGOPTIONS options; + dialog.GetOptions(&options); + EXPECT_EQ(options & FOS_ALLOWMULTISELECT, 0U); + EXPECT_EQ(options & FOS_PICKFOLDERS, 0U); + + return MockShowResult(fake_result_array); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = plugin.ShowOpenDialog( + SelectionOptions(/* allow multiple = */ false, + /* select folders = */ false, EncodableList()), + nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + ASSERT_EQ(paths.size(), 1); + EXPECT_EQ(std::get(paths[0]), + Utf8FromUtf16(fake_selected_file.path())); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +TEST(FileSelectorPlugin, TestOpenWithArguments) { + const HWND fake_window = reinterpret_cast(1337); + ScopedTestShellItem fake_selected_file; + IShellItemArrayPtr fake_result_array; + ::SHCreateShellItemArrayFromShellItem(fake_selected_file.file(), + IID_PPV_ARGS(&fake_result_array)); + + bool shown = false; + MockShow show_validator = [&shown, fake_result_array, fake_window]( + const TestFileDialogController& dialog, + HWND parent) { + shown = true; + EXPECT_EQ(parent, fake_window); + + // Validate arguments. + EXPECT_EQ(dialog.GetDialogFolderPath(), L"C:\\Program Files"); + // Make sure that the folder was called via SetFolder, not SetDefaultFolder. + EXPECT_EQ(dialog.GetSetFolderPath(), L"C:\\Program Files"); + EXPECT_EQ(dialog.GetOkButtonLabel(), L"Open it!"); + + return MockShowResult(fake_result_array); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + // This directory must exist. + std::string initial_directory("C:\\Program Files"); + std::string confirm_button("Open it!"); + ErrorOr result = plugin.ShowOpenDialog( + SelectionOptions(/* allow multiple = */ false, + /* select folders = */ false, EncodableList()), + &initial_directory, &confirm_button); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + ASSERT_EQ(paths.size(), 1); + EXPECT_EQ(std::get(paths[0]), + Utf8FromUtf16(fake_selected_file.path())); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +TEST(FileSelectorPlugin, TestOpenMultiple) { + const HWND fake_window = reinterpret_cast(1337); + ScopedTestFileIdList fake_selected_file_1; + ScopedTestFileIdList fake_selected_file_2; + LPCITEMIDLIST fake_selected_files[] = { + fake_selected_file_1.file(), + fake_selected_file_2.file(), + }; + IShellItemArrayPtr fake_result_array; + ::SHCreateShellItemArrayFromIDLists(2, fake_selected_files, + &fake_result_array); + + bool shown = false; + MockShow show_validator = [&shown, fake_result_array, fake_window]( + const TestFileDialogController& dialog, + HWND parent) { + shown = true; + EXPECT_EQ(parent, fake_window); + + // Validate options. + FILEOPENDIALOGOPTIONS options; + dialog.GetOptions(&options); + EXPECT_NE(options & FOS_ALLOWMULTISELECT, 0U); + EXPECT_EQ(options & FOS_PICKFOLDERS, 0U); + + return MockShowResult(fake_result_array); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = plugin.ShowOpenDialog( + SelectionOptions(/* allow multiple = */ true, + /* select folders = */ false, EncodableList()), + nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + ASSERT_EQ(paths.size(), 2); + EXPECT_EQ(std::get(paths[0]), + Utf8FromUtf16(fake_selected_file_1.path())); + EXPECT_EQ(std::get(paths[1]), + Utf8FromUtf16(fake_selected_file_2.path())); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +TEST(FileSelectorPlugin, TestOpenWithFilter) { + const HWND fake_window = reinterpret_cast(1337); + ScopedTestShellItem fake_selected_file; + IShellItemArrayPtr fake_result_array; + ::SHCreateShellItemArrayFromShellItem(fake_selected_file.file(), + IID_PPV_ARGS(&fake_result_array)); + + const EncodableValue text_group = + CustomEncodableValue(TypeGroup("Text", EncodableList({ + EncodableValue("txt"), + EncodableValue("json"), + }))); + const EncodableValue image_group = + CustomEncodableValue(TypeGroup("Images", EncodableList({ + EncodableValue("png"), + EncodableValue("gif"), + EncodableValue("jpeg"), + }))); + const EncodableValue any_group = + CustomEncodableValue(TypeGroup("Any", EncodableList())); + + bool shown = false; + MockShow show_validator = [&shown, fake_result_array, fake_window]( + const TestFileDialogController& dialog, + HWND parent) { + shown = true; + EXPECT_EQ(parent, fake_window); + + // Validate filter. + const std::vector& filters = dialog.GetFileTypes(); + EXPECT_EQ(filters.size(), 3U); + if (filters.size() == 3U) { + EXPECT_EQ(filters[0].name, L"Text"); + EXPECT_EQ(filters[0].spec, L"*.txt;*.json"); + EXPECT_EQ(filters[1].name, L"Images"); + EXPECT_EQ(filters[1].spec, L"*.png;*.gif;*.jpeg"); + EXPECT_EQ(filters[2].name, L"Any"); + EXPECT_EQ(filters[2].spec, L"*.*"); + } + + return MockShowResult(fake_result_array); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = + plugin.ShowOpenDialog(SelectionOptions(/* allow multiple = */ false, + /* select folders = */ false, + EncodableList({ + text_group, + image_group, + any_group, + })), + nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + ASSERT_EQ(paths.size(), 1); + EXPECT_EQ(std::get(paths[0]), + Utf8FromUtf16(fake_selected_file.path())); + // The test dialog controller always reports the last group as + // selected, so that should be what the plugin returns. + ASSERT_NE(result.value().type_group_index(), nullptr); + EXPECT_EQ(*(result.value().type_group_index()), 2); +} + +TEST(FileSelectorPlugin, TestOpenCancel) { + const HWND fake_window = reinterpret_cast(1337); + + bool shown = false; + MockShow show_validator = [&shown, fake_window]( + const TestFileDialogController& dialog, + HWND parent) { + shown = true; + return MockShowResult(); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = plugin.ShowOpenDialog( + SelectionOptions(/* allow multiple = */ false, + /* select folders = */ false, EncodableList()), + nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + EXPECT_EQ(paths.size(), 0); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +TEST(FileSelectorPlugin, TestSaveSimple) { + const HWND fake_window = reinterpret_cast(1337); + ScopedTestShellItem fake_selected_file; + + bool shown = false; + MockShow show_validator = + [&shown, fake_result = fake_selected_file.file(), fake_window]( + const TestFileDialogController& dialog, HWND parent) { + shown = true; + EXPECT_EQ(parent, fake_window); + + // Validate options. + FILEOPENDIALOGOPTIONS options; + dialog.GetOptions(&options); + EXPECT_EQ(options & FOS_ALLOWMULTISELECT, 0U); + EXPECT_EQ(options & FOS_PICKFOLDERS, 0U); + + return MockShowResult(fake_result); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = plugin.ShowSaveDialog( + SelectionOptions(/* allow multiple = */ false, + /* select folders = */ false, EncodableList()), + nullptr, nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + ASSERT_EQ(paths.size(), 1); + EXPECT_EQ(std::get(paths[0]), + Utf8FromUtf16(fake_selected_file.path())); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +TEST(FileSelectorPlugin, TestSaveWithArguments) { + const HWND fake_window = reinterpret_cast(1337); + ScopedTestShellItem fake_selected_file; + + bool shown = false; + MockShow show_validator = + [&shown, fake_result = fake_selected_file.file(), fake_window]( + const TestFileDialogController& dialog, HWND parent) { + shown = true; + EXPECT_EQ(parent, fake_window); + + // Validate arguments. + EXPECT_EQ(dialog.GetDialogFolderPath(), L"C:\\Program Files"); + // Make sure that the folder was called via SetFolder, not + // SetDefaultFolder. + EXPECT_EQ(dialog.GetSetFolderPath(), L"C:\\Program Files"); + EXPECT_EQ(dialog.GetFileName(), L"a name"); + EXPECT_EQ(dialog.GetOkButtonLabel(), L"Save it!"); + + return MockShowResult(fake_result); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + // This directory must exist. + std::string initial_directory("C:\\Program Files"); + std::string suggested_name("a name"); + std::string confirm_button("Save it!"); + ErrorOr result = plugin.ShowSaveDialog( + SelectionOptions(/* allow multiple = */ false, + /* select folders = */ false, EncodableList()), + &initial_directory, &suggested_name, &confirm_button); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + ASSERT_EQ(paths.size(), 1); + EXPECT_EQ(std::get(paths[0]), + Utf8FromUtf16(fake_selected_file.path())); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +TEST(FileSelectorPlugin, TestSaveWithFilter) { + const HWND fake_window = reinterpret_cast(1337); + ScopedTestShellItem fake_selected_file; + + const EncodableValue text_group = + CustomEncodableValue(TypeGroup("Text", EncodableList({ + EncodableValue("txt"), + EncodableValue("json"), + }))); + const EncodableValue image_group = + CustomEncodableValue(TypeGroup("Images", EncodableList({ + EncodableValue("png"), + EncodableValue("gif"), + EncodableValue("jpeg"), + }))); + + bool shown = false; + MockShow show_validator = + [&shown, fake_result = fake_selected_file.file(), fake_window]( + const TestFileDialogController& dialog, HWND parent) { + shown = true; + EXPECT_EQ(parent, fake_window); + + // Validate filter. + const std::vector& filters = dialog.GetFileTypes(); + EXPECT_EQ(filters.size(), 2U); + if (filters.size() == 2U) { + EXPECT_EQ(filters[0].name, L"Text"); + EXPECT_EQ(filters[0].spec, L"*.txt;*.json"); + EXPECT_EQ(filters[1].name, L"Images"); + EXPECT_EQ(filters[1].spec, L"*.png;*.gif;*.jpeg"); + } + + return MockShowResult(fake_result); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = + plugin.ShowSaveDialog(SelectionOptions(/* allow multiple = */ false, + /* select folders = */ false, + EncodableList({ + text_group, + image_group, + })), + nullptr, nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + ASSERT_EQ(paths.size(), 1); + EXPECT_EQ(std::get(paths[0]), + Utf8FromUtf16(fake_selected_file.path())); + // The test dialog controller always reports the last group as + // selected, so that should be what the plugin returns. + ASSERT_NE(result.value().type_group_index(), nullptr); + EXPECT_EQ(*(result.value().type_group_index()), 1); +} + +TEST(FileSelectorPlugin, TestSaveCancel) { + const HWND fake_window = reinterpret_cast(1337); + + bool shown = false; + MockShow show_validator = [&shown, fake_window]( + const TestFileDialogController& dialog, + HWND parent) { + shown = true; + return MockShowResult(); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = plugin.ShowSaveDialog( + SelectionOptions(/* allow multiple = */ false, + /* select folders = */ false, EncodableList()), + nullptr, nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + EXPECT_EQ(paths.size(), 0); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +TEST(FileSelectorPlugin, TestGetDirectorySimple) { + const HWND fake_window = reinterpret_cast(1337); + IShellItemPtr fake_selected_directory; + // This must be a directory that actually exists. + ::SHCreateItemFromParsingName(L"C:\\Program Files", nullptr, + IID_PPV_ARGS(&fake_selected_directory)); + IShellItemArrayPtr fake_result_array; + ::SHCreateShellItemArrayFromShellItem(fake_selected_directory, + IID_PPV_ARGS(&fake_result_array)); + + bool shown = false; + MockShow show_validator = [&shown, fake_result_array, fake_window]( + const TestFileDialogController& dialog, + HWND parent) { + shown = true; + EXPECT_EQ(parent, fake_window); + + // Validate options. + FILEOPENDIALOGOPTIONS options; + dialog.GetOptions(&options); + EXPECT_EQ(options & FOS_ALLOWMULTISELECT, 0U); + EXPECT_NE(options & FOS_PICKFOLDERS, 0U); + + return MockShowResult(fake_result_array); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = plugin.ShowOpenDialog( + SelectionOptions(/* allow multiple = */ false, + /* select folders = */ true, EncodableList()), + nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + ASSERT_EQ(paths.size(), 1); + EXPECT_EQ(std::get(paths[0]), "C:\\Program Files"); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +TEST(FileSelectorPlugin, TestGetDirectoryMultiple) { + const HWND fake_window = reinterpret_cast(1337); + // These are actual files, but since the plugin implementation doesn't + // validate the types of items returned from the system dialog, they are fine + // to use for unit tests. + ScopedTestFileIdList fake_selected_dir_1; + ScopedTestFileIdList fake_selected_dir_2; + LPCITEMIDLIST fake_selected_dirs[] = { + fake_selected_dir_1.file(), + fake_selected_dir_2.file(), + }; + IShellItemArrayPtr fake_result_array; + ::SHCreateShellItemArrayFromIDLists(2, fake_selected_dirs, + &fake_result_array); + + bool shown = false; + MockShow show_validator = [&shown, fake_result_array, fake_window]( + const TestFileDialogController& dialog, + HWND parent) { + shown = true; + EXPECT_EQ(parent, fake_window); + + // Validate options. + FILEOPENDIALOGOPTIONS options; + dialog.GetOptions(&options); + EXPECT_NE(options & FOS_ALLOWMULTISELECT, 0U); + EXPECT_NE(options & FOS_PICKFOLDERS, 0U); + + return MockShowResult(fake_result_array); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = plugin.ShowOpenDialog( + SelectionOptions(/* allow multiple = */ true, /* select folders = */ true, + EncodableList()), + nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + ASSERT_EQ(paths.size(), 2); + EXPECT_EQ(std::get(paths[0]), + Utf8FromUtf16(fake_selected_dir_1.path())); + EXPECT_EQ(std::get(paths[1]), + Utf8FromUtf16(fake_selected_dir_2.path())); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +TEST(FileSelectorPlugin, TestGetDirectoryCancel) { + const HWND fake_window = reinterpret_cast(1337); + + bool shown = false; + MockShow show_validator = [&shown, fake_window]( + const TestFileDialogController& dialog, + HWND parent) { + shown = true; + return MockShowResult(); + }; + + FileSelectorPlugin plugin( + [fake_window] { return fake_window; }, + std::make_unique(show_validator)); + ErrorOr result = plugin.ShowOpenDialog( + SelectionOptions(/* allow multiple = */ false, + /* select folders = */ true, EncodableList()), + nullptr, nullptr); + + EXPECT_TRUE(shown); + ASSERT_FALSE(result.has_error()); + const EncodableList& paths = result.value().paths(); + EXPECT_EQ(paths.size(), 0); + EXPECT_EQ(result.value().type_group_index(), nullptr); +} + +} // namespace test +} // namespace file_selector_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_file_dialog_controller.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_file_dialog_controller.cpp new file mode 100755 index 00000000..e775aa62 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_file_dialog_controller.cpp @@ -0,0 +1,128 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "test/test_file_dialog_controller.h" + +#include + +#include +#include +#include + +namespace file_selector_windows { +namespace test { + +TestFileDialogController::TestFileDialogController(IFileDialog* dialog, + MockShow mock_show) + : dialog_(dialog), + mock_show_(std::move(mock_show)), + FileDialogController(dialog) {} + +TestFileDialogController::~TestFileDialogController() {} + +HRESULT TestFileDialogController::SetFolder(IShellItem* folder) { + wchar_t* path_chars = nullptr; + if (SUCCEEDED(folder->GetDisplayName(SIGDN_FILESYSPATH, &path_chars))) { + set_folder_path_ = path_chars; + } else { + set_folder_path_ = L""; + } + + return FileDialogController::SetFolder(folder); +} + +HRESULT TestFileDialogController::SetFileTypes(UINT count, + COMDLG_FILTERSPEC* filters) { + filter_groups_.clear(); + for (unsigned int i = 0; i < count; ++i) { + filter_groups_.push_back( + DialogFilter(filters[i].pszName, filters[i].pszSpec)); + } + return FileDialogController::SetFileTypes(count, filters); +} + +HRESULT TestFileDialogController::SetOkButtonLabel(const wchar_t* text) { + ok_button_label_ = text; + return FileDialogController::SetOkButtonLabel(text); +} + +HRESULT TestFileDialogController::Show(HWND parent) { + mock_result_ = mock_show_(*this, parent); + if (std::holds_alternative(mock_result_)) { + return HRESULT_FROM_WIN32(ERROR_CANCELLED); + } + return S_OK; +} + +HRESULT TestFileDialogController::GetResult(IShellItem** out_item) const { + *out_item = std::get(mock_result_); + (*out_item)->AddRef(); + return S_OK; +} + +HRESULT TestFileDialogController::GetFileTypeIndex(UINT* out_index) const { + // Arbitrarily always return the last group. (No -1 because the return value + // from GetFileTypeIndex is defined to be one-indexed.) + *out_index = static_cast(filter_groups_.size()); + return S_OK; +} + +HRESULT TestFileDialogController::GetResults( + IShellItemArray** out_items) const { + *out_items = std::get(mock_result_); + (*out_items)->AddRef(); + return S_OK; +} + +std::wstring TestFileDialogController::GetSetFolderPath() const { + return set_folder_path_; +} + +std::wstring TestFileDialogController::GetDialogFolderPath() const { + IShellItemPtr item; + if (!SUCCEEDED(dialog_->GetFolder(&item))) { + return L""; + } + + wchar_t* path_chars = nullptr; + if (!SUCCEEDED(item->GetDisplayName(SIGDN_FILESYSPATH, &path_chars))) { + return L""; + } + std::wstring path(path_chars); + ::CoTaskMemFree(path_chars); + return path; +} + +std::wstring TestFileDialogController::GetFileName() const { + wchar_t* name_chars = nullptr; + if (!SUCCEEDED(dialog_->GetFileName(&name_chars))) { + return L""; + } + std::wstring name(name_chars); + ::CoTaskMemFree(name_chars); + return name; +} + +const std::vector& TestFileDialogController::GetFileTypes() + const { + return filter_groups_; +} + +std::wstring TestFileDialogController::GetOkButtonLabel() const { + return ok_button_label_; +} + +// ---------------------------------------- + +TestFileDialogControllerFactory::TestFileDialogControllerFactory( + MockShow mock_show) + : mock_show_(std::move(mock_show)) {} +TestFileDialogControllerFactory::~TestFileDialogControllerFactory() {} + +std::unique_ptr +TestFileDialogControllerFactory::CreateController(IFileDialog* dialog) const { + return std::make_unique(dialog, mock_show_); +} + +} // namespace test +} // namespace file_selector_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_file_dialog_controller.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_file_dialog_controller.h new file mode 100755 index 00000000..e3aa0936 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_file_dialog_controller.h @@ -0,0 +1,111 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_TEST_TEST_FILE_DIALOG_CONTROLLER_H_ +#define PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_TEST_TEST_FILE_DIALOG_CONTROLLER_H_ + +#include +#include +#include + +#include +#include +#include +#include + +#include "file_dialog_controller.h" +#include "test/test_utils.h" + +_COM_SMARTPTR_TYPEDEF(IFileDialog, IID_IFileDialog); + +namespace file_selector_windows { +namespace test { + +class TestFileDialogController; + +// A value to use for GetResult(s) in TestFileDialogController. The type depends +// on whether the dialog is an open or save dialog. +using MockShowResult = + std::variant; +// Called for TestFileDialogController::Show, to do validation and provide a +// mock return value for GetResult(s). +using MockShow = + std::function; + +// A C++-friendly version of a COMDLG_FILTERSPEC. +struct DialogFilter { + std::wstring name; + std::wstring spec; + + DialogFilter(const wchar_t* name, const wchar_t* spec) + : name(name), spec(spec) {} +}; + +// An extension of the normal file dialog controller that: +// - Allows for inspection of set values. +// - Allows faking the 'Show' interaction, providing tests an opportunity to +// validate the dialog settings and provide a return value, via MockShow. +class TestFileDialogController : public FileDialogController { + public: + TestFileDialogController(IFileDialog* dialog, MockShow mock_show); + ~TestFileDialogController(); + + // FileDialogController: + HRESULT SetFolder(IShellItem* folder) override; + HRESULT SetFileTypes(UINT count, COMDLG_FILTERSPEC* filters) override; + HRESULT SetOkButtonLabel(const wchar_t* text) override; + HRESULT Show(HWND parent) override; + HRESULT GetResult(IShellItem** out_item) const override; + HRESULT GetFileTypeIndex(UINT* out_index) const override; + HRESULT GetResults(IShellItemArray** out_items) const override; + + // Accessors for validating IFileDialogController setter calls. + // Gets the folder path set by FileDialogController::SetFolder. + // + // This exists because there are multiple ways that the value returned by + // GetDialogFolderPath can be changed, so this allows specifically validating + // calls to SetFolder. + std::wstring GetSetFolderPath() const; + // Gets dialog folder path by calling IFileDialog::GetFolder. + std::wstring GetDialogFolderPath() const; + std::wstring GetFileName() const; + const std::vector& GetFileTypes() const; + std::wstring GetOkButtonLabel() const; + + private: + IFileDialogPtr dialog_; + MockShow mock_show_; + MockShowResult mock_result_; + + // The last set values, for IFileDialog properties that have setters but no + // corresponding getters. + std::wstring set_folder_path_; + std::wstring ok_button_label_; + std::vector filter_groups_; +}; + +// A controller factory that vends TestFileDialogController instances. +class TestFileDialogControllerFactory : public FileDialogControllerFactory { + public: + // Creates a factory whose instances use mock_show for the Show callback. + TestFileDialogControllerFactory(MockShow mock_show); + virtual ~TestFileDialogControllerFactory(); + + // Disallow copy and assign. + TestFileDialogControllerFactory(const TestFileDialogControllerFactory&) = + delete; + TestFileDialogControllerFactory& operator=( + const TestFileDialogControllerFactory&) = delete; + + // FileDialogControllerFactory: + std::unique_ptr CreateController( + IFileDialog* dialog) const override; + + private: + MockShow mock_show_; +}; + +} // namespace test +} // namespace file_selector_windows + +#endif // PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_TEST_TEST_FILE_DIALOG_CONTROLLER_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_main.cpp new file mode 100755 index 00000000..5a49b52c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_main.cpp @@ -0,0 +1,16 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include +#include + +int main(int argc, char** argv) { + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + testing::InitGoogleTest(&argc, argv); + int exit_code = RUN_ALL_TESTS(); + + ::CoUninitialize(); + + return exit_code; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_utils.cpp new file mode 100755 index 00000000..3e3ab98a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_utils.cpp @@ -0,0 +1,45 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "test/test_utils.h" + +#include +#include + +#include + +namespace file_selector_windows { +namespace test { + +namespace { + +// Creates a temp file and returns its path. +std::wstring CreateTempFile() { + wchar_t temp_dir[MAX_PATH]; + wchar_t temp_file[MAX_PATH]; + wchar_t long_path[MAX_PATH]; + ::GetTempPath(MAX_PATH, temp_dir); + ::GetTempFileName(temp_dir, L"test", 0, temp_file); + // Convert to long form to match what IShellItem queries will return. + ::GetLongPathName(temp_file, long_path, MAX_PATH); + return long_path; +} + +} // namespace + +ScopedTestShellItem::ScopedTestShellItem() { + path_ = CreateTempFile(); + ::SHCreateItemFromParsingName(path_.c_str(), nullptr, IID_PPV_ARGS(&item_)); +} + +ScopedTestShellItem::~ScopedTestShellItem() { ::DeleteFile(path_.c_str()); } + +ScopedTestFileIdList::ScopedTestFileIdList() { + path_ = CreateTempFile(); + item_ = ItemIdListPtr(::ILCreateFromPath(path_.c_str())); +} + +ScopedTestFileIdList::~ScopedTestFileIdList() { ::DeleteFile(path_.c_str()); } + +} // namespace test +} // namespace file_selector_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_utils.h new file mode 100755 index 00000000..34106c50 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/file_selector_windows/windows/test/test_utils.h @@ -0,0 +1,91 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_TEST_TEST_UTILS_H_ +#define PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_TEST_TEST_UTILS_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "file_dialog_controller.h" + +_COM_SMARTPTR_TYPEDEF(IShellItem, IID_IShellItem); +_COM_SMARTPTR_TYPEDEF(IShellItemArray, IID_IShellItemArray); + +namespace file_selector_windows { +namespace test { + +// Creates a temp file, managed as an IShellItem, which will be deleted when +// the instance goes out of scope. +// +// This creates a file on the filesystem since creating IShellItem instances for +// files that don't exist is non-trivial. +class ScopedTestShellItem { + public: + ScopedTestShellItem(); + ~ScopedTestShellItem(); + + // Disallow copy and assign. + ScopedTestShellItem(const ScopedTestShellItem&) = delete; + ScopedTestShellItem& operator=(const ScopedTestShellItem&) = delete; + + // Returns the file's IShellItem reference. + IShellItemPtr file() { return item_; } + + // Returns the file's path. + const std::wstring& path() { return path_; } + + private: + IShellItemPtr item_; + std::wstring path_; +}; + +// Creates a temp file, managed as an ITEMIDLIST, which will be deleted when +// the instance goes out of scope. +// +// This creates a file on the filesystem since creating IShellItem instances for +// files that don't exist is non-trivial, and this is intended for use in +// creating IShellItemArray instances. +class ScopedTestFileIdList { + public: + ScopedTestFileIdList(); + ~ScopedTestFileIdList(); + + // Disallow copy and assign. + ScopedTestFileIdList(const ScopedTestFileIdList&) = delete; + ScopedTestFileIdList& operator=(const ScopedTestFileIdList&) = delete; + + // Returns the file's ITEMIDLIST reference. + PIDLIST_ABSOLUTE file() { return item_.get(); } + + // Returns the file's path. + const std::wstring& path() { return path_; } + + private: + // Smart pointer for managing ITEMIDLIST instances. + struct ItemIdListDeleter { + void operator()(LPITEMIDLIST item) { + if (item) { + ::ILFree(item); + } + } + }; + using ItemIdListPtr = std::unique_ptr, + ItemIdListDeleter>; + + ItemIdListPtr item_; + std::wstring path_; +}; + +} // namespace test +} // namespace file_selector_windows + +#endif // PACKAGES_FILE_SELECTOR_FILE_SELECTOR_WINDOWS_WINDOWS_TEST_TEST_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows deleted file mode 120000 index 6571dfe9..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_windows-1.0.3/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/CHANGELOG.md new file mode 100755 index 00000000..5a33e5ed --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/CHANGELOG.md @@ -0,0 +1,15 @@ +## [1.0.3] + +* Fixed issue where non-ASCII characters for the notification [application name](https://pub.dev/documentation/flutter_local_notifications/latest/flutter_local_notifications/WindowsInitializationSettings/appName.html) weren't being displayed properly. Thanks to the PR from [yoyoIU](https://github.com/yoyo930021) + +## [1.0.2] + +* Fixed issue [#2648](https://github.com/MaikuB/flutter_local_notifications/issues/2648) where non-ASCII characters in the notification payload were not being handled properly. Thanks to the PR from [yoyoIU](https://github.com/yoyo930021) + +## [1.0.1] + +* Fixed issue [#2651](https://github.com/MaikuB/flutter_local_notifications/issues/2651) where unresolved symbols occurred with changes in introduced in newer Windows SDKs. Thanks to the PR from [Sebastien](https://github.com/Sebastien-VZN) + +## [1.0.0] + +* Initial release for Windows. Thanks to PR [Levi Lesches](https://github.com/Levi-Lesches) that continued the work done initially done by [Kenneth](https://github.com/kennethnym) and [lightrabbit](https://github.com/lightrabbit) \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/LICENSE new file mode 100755 index 00000000..41917706 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/LICENSE @@ -0,0 +1,27 @@ +Copyright 2024 Michael Bui. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/README.md new file mode 100755 index 00000000..09b1d0c2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/README.md @@ -0,0 +1,48 @@ +# flutter_local_notifications_windows + +The Windows implementation of `package:flutter_local_notifications` as an FFI package that can be run in plain Dart or as a Flutter plugin. See [the docs on FFI](https://dart.dev/interop/c-interop). + +## Limitations + +- Windows does not support repeating notifications, so [`periodicallyShow`](https://pub.dev/documentation/flutter_local_notifications/latest/flutter_local_notifications/FlutterLocalNotificationsPlugin/periodicallyShow.html) and [`periodicallyShowWithDuration`](https://pub.dev/documentation/flutter_local_notifications/latest/flutter_local_notifications/FlutterLocalNotificationsPlugin/periodicallyShowWithDuration.html) will throw `UnsupportedError`s. +- Windows only allows apps with package identity to retrieve previously shown notifications. This means that on an app that was not packaged as an [MSIX](https://learn.microsoft.com/en-us/windows/msix/overview) installer, [`cancel`](https://pub.dev/documentation/flutter_local_notifications/latest/flutter_local_notifications/FlutterLocalNotificationsPlugin/cancel.html) does nothing and [getActiveNotifications](https://pub.dev/documentation/flutter_local_notifications/latest/flutter_local_notifications/FlutterLocalNotificationsPlugin/getActiveNotifications.html) will return an empty list. To package your app as an MSIX, see [`package:msix`](https://pub.dev/packages/msix) and the `msix` section in [the example's `pubspec.yaml`](https://github.com/MaikuB/flutter_local_notifications/blob/master/flutter_local_notifications/example/pubspec.yaml). + +## Project structure + +This template uses the following structure: + +- `src`: Contains the native source code, and a CmakeFile.txt file for building + that source code into a dynamic library. Within this folder, there are three C++ files: + - `ffi_api.h`/`ffi_api.cpp`: A C-compatible header file with the API that will be used by Dart, and the C++ implementation of that API + - `plugin.hpp`/`plugin.cpp`: A C++ class holding handles to the [C++/WinRT](https://learn.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/) SDK, along with some Windows-heavy logic. `ffi_api.cpp` implements its features using this class. + - `utils.hpp`/`utils.cpp` handle copying and allocating data from C structs to WinRT classes and vice-versa. Since FFI is done over C-based APIs, C++ types like strings, maps, and vectors need to be translated. + +- `lib`: Contains the Dart code that defines the API of the plugin, and which + calls into the native code using `dart:ffi`. + - The `details` folder holds all the Windows-specific notification configurations such as `WindowsAction`, `WindowsImage`, etc. + - The `ffi` folder holds the generated bindings (see below) and other FFI utilities. + - The `plugin` folder implements `package:flutter_local_notifications_platform_interface` in two ways: a stub for platforms that don't support FFI, and an FFI-based implementation. + +- The `windows` folder contains the build files for building and bundling the native code library with the platform application. + +## Building and bundling native code + +The code in `src` can be built with CMake. A `build.bat` file is included, which has the following code: + +```batch +@echo off +cd build +cmake ../windows +cmake --build . +cd .. +copy build\shared\Debug\flutter_local_notifications_windows.dll . +``` + +This generates a DLL from the native code and copies it to the current directory. This is useful for testing locally without Flutter. When using Flutter, this step is unnecessary as Flutter will build and bundle the assets for you. + +## Binding to native code + +To use the native code, bindings in Dart are needed. +To avoid writing these by hand, they are generated from the header file +`src/ffi_api.h` by `package:ffigen`. +Regenerate the bindings by running `dart run ffigen --config ffigen.yaml`. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/build.bat b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/build.bat new file mode 100755 index 00000000..25d81f28 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/build.bat @@ -0,0 +1,7 @@ +@echo off +if not exist build mkdir build +cd build +cmake ../windows +cmake --build . +cd .. +copy build\shared\Debug\flutter_local_notifications_windows.dll . diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/dart_test.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/dart_test.yaml new file mode 100755 index 00000000..0675cf5b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/dart_test.yaml @@ -0,0 +1,2 @@ +platforms: [vm] +test_on: windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/ffigen.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/ffigen.yaml new file mode 100755 index 00000000..aad4b5e0 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/ffigen.yaml @@ -0,0 +1,31 @@ +# Run with `dart run ffigen --config ffigen.yaml`. +name: NotificationsPluginBindings +description: | + Bindings for `src/ffi_api.h`. + + Regenerate bindings with `dart run ffigen --config ffigen.yaml`. +output: 'lib/src/ffi/bindings.dart' + +silence-enum-warning: true + +headers: + entry-points: + - 'src/ffi_api.h' + include-directives: + - 'src/ffi_api.h' + +preamble: | + // ignore_for_file: always_specify_types + // ignore_for_file: camel_case_types + // ignore_for_file: non_constant_identifier_names + +comments: + style: any + length: full + +type-map: + native-types: + 'char': # Converts `char` to `Utf8` instead of `Char` + 'lib': 'pkg_ffi' + 'c-type': 'Utf8' + 'dart-type': 'Utf8' diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/flutter_local_notifications_windows.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/flutter_local_notifications_windows.dart new file mode 100755 index 00000000..ed3b9c82 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/flutter_local_notifications_windows.dart @@ -0,0 +1,3 @@ +export 'src/details.dart'; +export 'src/msix/stub.dart' if (dart.library.ffi) 'src/msix/ffi.dart'; +export 'src/plugin/stub.dart' if (dart.library.ffi) 'src/plugin/ffi.dart'; diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details.dart new file mode 100755 index 00000000..a6902709 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details.dart @@ -0,0 +1,21 @@ +export 'details/initialization_settings.dart'; +export 'details/notification_action.dart'; +export 'details/notification_audio.dart'; +export 'details/notification_details.dart'; +export 'details/notification_header.dart'; +export 'details/notification_input.dart'; +export 'details/notification_parts.dart'; +export 'details/notification_progress.dart'; +export 'details/notification_row.dart'; + +/// The result of updating a notification. +enum NotificationUpdateResult { + /// The update was successful. + success, + + /// There was an unexpected error updating the notification. + error, + + /// No notification with the provided ID could be found. + notFound, +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/initialization_settings.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/initialization_settings.dart new file mode 100755 index 00000000..507d8592 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/initialization_settings.dart @@ -0,0 +1,26 @@ +/// Plugin initialization settings for Windows. +class WindowsInitializationSettings { + /// Creates a new settings object for initializing this plugin on Windows. + const WindowsInitializationSettings({ + required this.appName, + required this.appUserModelId, + required this.guid, + this.iconPath, + }); + + /// The name of the app that should be shown in the notification toast. + final String appName; + + /// The unique app user model ID that identifies the app, + /// in the form of CompanyName.ProductName.SubProduct.VersionInformation. + /// + /// See https://docs.microsoft.com/en-us/windows/win32/shell/appids + /// for more information. + final String appUserModelId; + + /// The GUID that identifies the notification activation callback. + final String guid; + + /// The path to the icon of the notification. + final String? iconPath; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_action.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_action.dart new file mode 100755 index 00000000..49ac5dc6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_action.dart @@ -0,0 +1,106 @@ +import 'notification_parts.dart'; + +// NOTE: All enum values in this file have Windows RT-specific names. +// If you change their Dart names, be sure to override [Enum.name]. + +/// Decides how the [WindowsAction] will launch the app. +enum WindowsActivationType { + /// The application will launch in the foreground (the default). + foreground, + + /// Any application can be launched using its protocol. + protocol, +} + +/// Decides how a [WindowsAction] will react to being pressed. +enum WindowsNotificationBehavior { + /// The notification will be dismissed. + dismiss('default'), + + /// The notification will remain on screen and show a loading status. + pendingUpdate('pendingUpdate'); + + const WindowsNotificationBehavior(this.name); + + /// The Windows API name for this choice. + final String name; +} + +/// Decides how a [WindowsAction] will be styled. +enum WindowsButtonStyle { + /// A green button. + success('Success'), + + /// A red button. + critical('Critical'); + + const WindowsButtonStyle(this.name); + + /// The Windows API name for this choice. + final String name; +} + +/// Decides how a [WindowsAction] is placed on a notification. +enum WindowsActionPlacement { + /// Instead of a separate button, the action is part of the context menu. + contextMenu, +} + +/// A button in a Windows notification. +/// +/// See https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-action#attributes +class WindowsAction { + /// Constructs a Windows notification button from parameters. + const WindowsAction({ + required this.content, + required this.arguments, + this.activationType = WindowsActivationType.foreground, + this.activationBehavior = WindowsNotificationBehavior.dismiss, + this.placement, + this.imageUri, + this.inputId, + this.buttonStyle, + this.tooltip, + }); + + /// The body text of the button. + final String content; + + /// An app-defined string that will be passed back if the button is pressed. + final String arguments; + + /// How the application should open if the button is pressed. + /// + /// The default value is [WindowsActivationType.foreground]. + final WindowsActivationType activationType; + + /// How the notification should react when the button is pressed. + /// + /// The default value is [WindowsNotificationBehavior.dismiss]. + final WindowsNotificationBehavior activationBehavior; + + /// How the button should be placed on the notification. + /// + /// Null indicates a regular button. + final WindowsActionPlacement? placement; + + /// An image to show on the button. + /// + /// Images must be white with a transparent background, and should be + /// 16x16 pixels with no padding. If you provide an image for one button, + /// you should provide images for all your buttons. + /// + /// Check the docs for [WindowsImage] for an explanation of supported URIs. + final Uri? imageUri; + + /// The ID of an input box. + /// + /// If provided, this button will be placed next to the specified input. + final String? inputId; + + /// The style of the button. Null indicates a plain button. + final WindowsButtonStyle? buttonStyle; + + /// The tooltip, useful if [content] is empty. + final String? tooltip; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_audio.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_audio.dart new file mode 100755 index 00000000..4c5ff847 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_audio.dart @@ -0,0 +1,126 @@ +import '../../flutter_local_notifications_windows.dart'; + +/// A preset sound for a Windows notification. +enum WindowsNotificationSound { + /// The default sound. + defaultSound('ms-winsoundevent:Notification.Default'), + + /// The IM sound. + im('ms-winsoundevent:Notification.IM'), + + /// The Mail sound. + mail('ms-winsoundevent:Notification.Mail'), + + /// The Reminder sound. + reminder('ms-winsoundevent:Notification.Reminder'), + + /// The SMS sound. + sms('ms-winsoundevent:Notification.SMS'), + + /// Alarm sound 1. + alarm1('ms-winsoundevent:Notification.Looping.Alarm1'), + + /// Alarm sound 2. + alarm2('ms-winsoundevent:Notification.Looping.Alarm2'), + + /// Alarm sound 3. + alarm3('ms-winsoundevent:Notification.Looping.Alarm3'), + + /// Alarm sound 4. + alarm4('ms-winsoundevent:Notification.Looping.Alarm4'), + + /// Alarm sound 5. + alarm5('ms-winsoundevent:Notification.Looping.Alarm5'), + + /// Alarm sound 6. + alarm6('ms-winsoundevent:Notification.Looping.Alarm6'), + + /// Alarm sound 7. + alarm7('ms-winsoundevent:Notification.Looping.Alarm7'), + + /// Alarm sound 8. + alarm8('ms-winsoundevent:Notification.Looping.Alarm8'), + + /// Alarm sound 9. + alarm9('ms-winsoundevent:Notification.Looping.Alarm9'), + + /// Alarm sound 10. + alarm10('ms-winsoundevent:Notification.Looping.Alarm10'), + + /// Call sound 1. + call1('ms-winsoundevent:Notification.Looping.Call1'), + + /// Call sound 2. + call2('ms-winsoundevent:Notification.Looping.Call2'), + + /// Call sound 3. + call3('ms-winsoundevent:Notification.Looping.Call3'), + + /// Call sound 4. + call4('ms-winsoundevent:Notification.Looping.Call4'), + + /// Call sound 5. + call5('ms-winsoundevent:Notification.Looping.Call5'), + + /// Call sound 6. + call6('ms-winsoundevent:Notification.Looping.Call6'), + + /// Call sound 7. + call7('ms-winsoundevent:Notification.Looping.Call7'), + + /// Call sound 8. + call8('ms-winsoundevent:Notification.Looping.Call8'), + + /// Call sound 9. + call9('ms-winsoundevent:Notification.Looping.Call9'), + + /// Call sound 10. + call10('ms-winsoundevent:Notification.Looping.Call10'); + + const WindowsNotificationSound(this.name); + + /// The Windows API name for this sound. + final String name; +} + +/// Specifies custom audio to play during a notification. +class WindowsNotificationAudio { + /// No sound will play during this notification. + WindowsNotificationAudio.silent() + : source = WindowsNotificationSound.defaultSound.name, + shouldLoop = false, + isSilent = true; + + /// Audio from a Windows preset. See [WindowsNotificationSound] for options. + WindowsNotificationAudio.preset({ + required WindowsNotificationSound sound, + this.shouldLoop = false, + }) : isSilent = false, + source = sound.name; + + /// Uses an audio file from a Flutter asset. + /// + /// Note that this will only work in release builds that have been packaged as + /// an MSIX installer. If you pass a [WindowsNotificationSound] for `fallback` + /// it will be used in debug and releases without MSIX. + /// + /// Windows supports the following formats: `.aac`, `.flac`, `.m4a`, `.mp3`, + /// `.wav`, and `.wma`. + WindowsNotificationAudio.asset( + String assetName, { + this.shouldLoop = false, + WindowsNotificationSound fallback = WindowsNotificationSound.defaultSound, + }) : isSilent = false, + source = MsixUtils.hasPackageIdentity() + ? MsixUtils.getAssetUri(assetName).toString() + : fallback.name; + + /// Whether this audio should loop. + final bool shouldLoop; + + /// Whether this notification should be silent. + final bool isSilent; + + /// The source of the audio. + final String source; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_details.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_details.dart new file mode 100755 index 00000000..255224d5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_details.dart @@ -0,0 +1,102 @@ +import 'notification_action.dart'; +import 'notification_audio.dart'; +import 'notification_header.dart'; +import 'notification_input.dart'; +import 'notification_parts.dart'; +import 'notification_progress.dart'; +import 'notification_row.dart'; + +export 'notification_parts.dart'; + +/// The duration for a Windows notification. +enum WindowsNotificationDuration { + /// The notification will stay for a long time. + long, + + /// The notification will stay for a short time. + short, +} + +/// The scenario a notification is being used for. +enum WindowsNotificationScenario { + /// Reminders are expanded and remain until manually dismissed. + /// + /// This will be ignored unless the notification also has at least one + /// [WindowsAction] that activates a background task. + reminder, + + /// Alarms are expanded and remain until manually dismissed. + /// + /// By default, alarm notifications loop the standard "alarm" sound. + alarm, + + /// Calls are expanded and show in a special format. + /// + /// By default, call notifications loop the standard "call" sound. + incomingCall, + + /// Urgent notifications can break through Do Not Disturb settings. + urgent, +} + +/// Contains notification details specific to Windows. +/// +/// See: https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts +class WindowsNotificationDetails { + /// Creates a Windows notification from the given options. + const WindowsNotificationDetails({ + this.actions = const [], + this.inputs = const [], + this.images = const [], + this.rows = const [], + this.progressBars = const [], + this.bindings = const {}, + this.header, + this.audio, + this.duration, + this.scenario, + this.timestamp, + this.subtitle, + }); + + /// A list of at most five action buttons. + final List actions; + + /// A list of at most five input elements. + final List inputs; + + /// A custom audio to play during this notification. + final WindowsNotificationAudio? audio; + + /// The duration for this notification. + final WindowsNotificationDuration? duration; + + /// The scenario for this notification. Sets some defaults based on the value. + final WindowsNotificationScenario? scenario; + + /// The header for this group of notifications. + final WindowsHeader? header; + + /// Overrides the timestamp to show on the notification. + final DateTime? timestamp; + + /// A third line to show under the notification body. + final String? subtitle; + + /// A list of images to show. + final List images; + + /// A list of rows to show. + final List rows; + + /// A list of progress bars to show. + final List progressBars; + + /// Custom bindings in the notification. + /// + /// Text elements can contains "bindings", which are entered as + /// `{bindingName}` directly into the string values. You can then update them + /// while or after the notification is launched by using the binding name as + /// the key here, and the value as any string you want. + final Map bindings; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_header.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_header.dart new file mode 100755 index 00000000..a5fbd14f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_header.dart @@ -0,0 +1,31 @@ +/// Decides how the application will open when the header is pressed. +enum WindowsHeaderActivation { + /// Opens the app in the foreground. + foreground, + + /// Opens any app using a custom protocol. + protocol, +} + +/// A header that groups multiple Windows notifications. +class WindowsHeader { + /// Creates a Windows header. + const WindowsHeader({ + required this.id, + required this.title, + required this.arguments, + this.activation, + }); + + /// A unique ID for this header. + final String id; + + /// The title of the header. + final String title; + + /// An application-defined payload that will be passed back when pressed. + final String arguments; + + /// Specifies how the application will open. + final WindowsHeaderActivation? activation; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_input.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_input.dart new file mode 100755 index 00000000..f13291ef --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_input.dart @@ -0,0 +1,74 @@ +/// The type of a [WindowsInput]. +enum WindowsInputType { + /// A text input. + text, + + /// A multiple choice input. + selection, +} + +/// A text or multiple choice input element in a Windows notification. +sealed class WindowsInput { + /// Creates an input field in a notification. + const WindowsInput({ + required this.id, + required this.type, + this.title, + }); + + /// A unique ID for this input. + /// + /// Can be used by buttons to be placed next to this input. + final String id; + + /// The type of this input. + final WindowsInputType type; + + /// The title of this input. + final String? title; +} + +/// A text input. +class WindowsTextInput extends WindowsInput { + /// Creates an input field in a notification. + const WindowsTextInput({ + required super.id, + this.placeHolderContent, + super.title, + }) : super(type: WindowsInputType.text); + + /// A placeholder shown before the user enters input, like a hint text. + final String? placeHolderContent; +} + +/// A multiple choice input. +class WindowsSelectionInput extends WindowsInput { + /// Creates a selection input. + const WindowsSelectionInput({ + required super.id, + required this.items, + this.defaultItem, + super.title, + }) : super(type: WindowsInputType.selection); + + /// The items that can be selected. + final List items; + + /// The default item that is selected. + final String? defaultItem; +} + +/// An option that can be selected by a [WindowsSelectionInput]. +class WindowsSelection { + /// Creates a selectable choice. + const WindowsSelection({ + required this.id, + required this.content, + }); + + /// A unique ID for this item. + final String id; + + /// The content of this item in the UI. + final String content; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_parts.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_parts.dart new file mode 100755 index 00000000..54e07929 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_parts.dart @@ -0,0 +1,139 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import '../../flutter_local_notifications_windows.dart'; + +/// A text or image element in a Windows notification. +/// +/// Note: This should not be used for anything else as notification +/// groups can only contain text and images. +// This class needs to be abstract so [WindowsNotificationText] and +// [WindowsImage] can extend it. Specifically, this class is a marker +// type for classes that are valid as part of a [WindowsColumn]. +// ignore: one_member_abstracts +sealed class WindowsNotificationPart { + /// A const constructor. + const WindowsNotificationPart(); +} + +/// Where a Windows notification image can be placed. +enum WindowsImagePlacement { + /// The image replaces the app logo. + appLogoOverride, + + /// The image is shown on top of the notification body. + hero, +} + +/// How a Windows notification image can be cropped. +enum WindowsImageCrop { + /// The image is cropped into a circle. + circle, +} + +/// An image in a Windows notification. +/// +/// Windows supports a few different URI types, and supports them differently +/// depending on if your app is packaged as an MSIX. Refer to the following: +/// +/// | URI | Debug | Release (EXE) | Release (MSIX) | +/// |--------|--------|--------|--------| +/// | `http(s)://` | ❌ | ❌ | ✅ | +/// | `ms-appx://` | ❌ | ❌ | ✅ | +/// | `file:///` | ✅ | ✅ | 🟨 | +/// | `getAssetUri()` | ✅ | ✅ | ✅ | +/// +/// Each URI type has different uses: +/// - For Flutter assets, use [getAssetUri], which return the correct file URI +/// for debug and release (exe) builds, and an `ms-appx` URI in MSIX builds. +/// - For images from the web, use an `https` or `http` URI, but note that +/// these only work in MSIX apps. If you need a network image without using +/// MSIX, consider downloading it directly and using a file URI after. Also +/// note that showing the notification will cause the image to be downloaded, +/// which could cause a small delay. Try to use small images. +/// - For images that come from the user's device, or have to be retrieved at +/// runtime, use a file URI, but as always, be aware of how paths might change +/// from your device to your users. Note that file URIs must be absolute +/// paths, not relative, which can be complicated if referring to MSIX assets. +/// - For images that are bundled with your app but not through Flutter, use +/// an `ms-appx` URI. +class WindowsImage extends WindowsNotificationPart { + /// Creates a Windows notification image from an image URI. + const WindowsImage( + this.uri, { + required this.altText, + this.addQueryParams = false, + this.placement, + this.crop, + }); + + /// Returns a URI for a [Flutter asset](https://docs.flutter.dev/ui/assets/assets-and-images#loading-images). + /// + /// - In debug mode, resolves to a file URI to the asset itself + /// - In non-MSIX release builds, resolves to a file URI to the bundled asset + /// - In MSIX releases, resolves to an `ms-appx` URI from [Msix.getAssetUri]. + static Uri getAssetUri(String assetName) { + if (kDebugMode) { + return Uri.file(File(assetName).absolute.path, windows: true); + } else if (MsixUtils.hasPackageIdentity()) { + return MsixUtils.getAssetUri(assetName); + } else { + return Uri.file( + File('data/flutter_assets/$assetName').absolute.path, + windows: true, + ); + } + } + + /// Whether Windows should add URL query parameters when fetching the image. + final bool addQueryParams; + + /// A description of the image to be used by assistive technology. + final String altText; + + /// The source of the image. + final Uri uri; + + /// Where this image will be placed. Null indicates below the notification. + final WindowsImagePlacement? placement; + + /// How the image will be cropped. Null indicates uncropped. + final WindowsImageCrop? crop; +} + +/// Where text can be placed in a Windows notification. +enum WindowsTextPlacement { + /// Shown at the bottom of the notification body in smaller text. + attribution, +} + +/// Text in a Windows notification. +/// +/// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-text +class WindowsNotificationText extends WindowsNotificationPart { + /// Creates text for a Windows notification. + const WindowsNotificationText({ + required this.text, + this.centerIfCall = false, + this.isCaption = false, + this.placement, + this.languageCode, + }); + + /// The text being displayed. + final String text; + + /// Whether to center this text. Only relevant if in an incoming call. + final bool centerIfCall; + + /// Whether the text should be smaller like a caption. + final bool isCaption; + + /// The placement of this text. + /// + /// The default placement (null) is in the main body of the notification. + final WindowsTextPlacement? placement; + + /// The language of this text. + final String? languageCode; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_progress.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_progress.dart new file mode 100755 index 00000000..f7847a42 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_progress.dart @@ -0,0 +1,35 @@ +import '../../flutter_local_notifications_windows.dart'; + +/// A progress bar in a Windows notification. +/// +/// To update the progress after the notification has been shown, +/// use [FlutterLocalNotificationsWindows.updateProgressBar]. +class WindowsProgressBar { + /// Creates a progress bar for a Windows notification. + WindowsProgressBar({ + required this.id, + required this.status, + required this.value, + this.title, + this.label, + }); + + /// A unique ID for this progress bar. + final String id; + + /// An optional title. + final String? title; + + /// Describes what's happening, like `Downloading...` or `Installing...` + final String status; + + /// The value of the progress, from 0.0 to 1.0. + /// + /// Setting this to null indicates a indeterminate progress bar. + double? value; + + /// Overrides the default reading as a percent with a different text. + /// + /// Useful for indicating discrete progress, like `3/10` instead of `30%`. + String? label; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_row.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_row.dart new file mode 100755 index 00000000..8e3f6a9f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_row.dart @@ -0,0 +1,21 @@ +import 'notification_parts.dart'; + +/// A group of notification content that must be displayed as a whole row. +/// +/// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-group +class WindowsRow { + /// Makes a group of multiple columns. + const WindowsRow(this.columns); + + /// The different columns being grouped together. + final List columns; +} + +/// A vertical column of text and images in a Windows notification. +class WindowsColumn { + /// A const constructor. + const WindowsColumn(this.parts); + + /// A list of text or images in this column. + final List parts; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_to_xml.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_to_xml.dart new file mode 100755 index 00000000..67184c1b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/notification_to_xml.dart @@ -0,0 +1,47 @@ +import 'package:xml/xml.dart'; + +import '../../flutter_local_notifications_windows.dart'; +import 'xml/details.dart'; + +export 'xml/progress.dart'; + +/// Converts a notification with [WindowsNotificationDetails] into XML. +/// +/// For more details, refer to the [Toast Notification XML schema](https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/schema-root). +String notificationToXml({ + String? title, + String? body, + String? payload, + WindowsNotificationDetails? details, +}) { + final XmlBuilder builder = XmlBuilder(); + builder.element( + 'toast', + attributes: { + ...details?.attributes ?? {}, + if (payload != null) 'launch': payload, + if (details?.scenario == null) 'useButtonStyle': 'true', + }, + nest: () { + builder.element( + 'visual', + nest: () { + builder.element( + 'binding', + attributes: {'template': 'ToastGeneric'}, + nest: () { + builder + ..element('text', nest: title) + ..element('text', nest: body); + details?.generateBinding(builder); + }, + ); + }, + ); + details?.buildXml(builder); + }, + ); + return builder + .buildDocument() + .toXmlString(pretty: true, indentAttribute: (_) => true); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/action.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/action.dart new file mode 100755 index 00000000..d31a3468 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/action.dart @@ -0,0 +1,25 @@ +import 'package:xml/xml.dart'; +import '../notification_action.dart'; + +/// Converts a [WindowsAction] to XML +extension ActionToXml on WindowsAction { + /// Serializes this notification action as Windows-compatible XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-action#syntax + void buildXml(XmlBuilder builder) { + builder.element( + 'action', + attributes: { + 'content': content, + 'arguments': arguments, + 'activationType': activationType.name, + 'afterActivationBehavior': activationBehavior.name, + if (placement != null) 'placement': placement!.name, + if (imageUri != null) 'imageUri': imageUri!.toString(), + if (inputId != null) 'hint-inputId': inputId!, + if (buttonStyle != null) 'hint-buttonStyle': buttonStyle!.name, + if (tooltip != null) 'hint-toolTip': tooltip!, + }, + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/audio.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/audio.dart new file mode 100755 index 00000000..586a53f0 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/audio.dart @@ -0,0 +1,17 @@ +import 'package:xml/xml.dart'; +import '../notification_audio.dart'; + +/// Converts a [WindowsNotificationAudio] to XML +extension AudioToXml on WindowsNotificationAudio { + /// Serializes this audio to Windows-compatible XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-audio + void buildXml(XmlBuilder builder) => builder.element( + 'audio', + attributes: { + 'src': source, + 'silent': isSilent.toString(), + 'loop': shouldLoop.toString(), + }, + ); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/details.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/details.dart new file mode 100755 index 00000000..98ba8d6a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/details.dart @@ -0,0 +1,91 @@ +import 'package:xml/xml.dart'; + +import '../notification_action.dart'; +import '../notification_details.dart'; +import '../notification_input.dart'; +import '../notification_progress.dart'; +import '../notification_row.dart'; + +import 'action.dart'; +import 'audio.dart'; +import 'header.dart'; +import 'image.dart'; +import 'input.dart'; +import 'progress.dart'; +import 'row.dart'; + +extension on DateTime { + String toIso8601StringTz() { + // Get offset + final Duration offset = timeZoneOffset; + final String sign = offset.isNegative ? '-' : '+'; + final String hours = offset.inHours.abs().toString().padLeft(2, '0'); + final String minutes = + offset.inMinutes.abs().remainder(60).toString().padLeft(2, '0'); + final String offsetString = '$sign$hours:$minutes'; + // Get first part of properly formatted ISO 8601 date + final String formattedDate = toIso8601String().split('.').first; + return '$formattedDate$offsetString'; + } +} + +/// Converts a [WindowsNotificationDetails] to XML +extension DetailsToXml on WindowsNotificationDetails { + /// Builds all relevant XML parts under the root `` element. + void buildXml(XmlBuilder builder) { + if (actions.length > 5) { + throw ArgumentError( + 'WindowsNotificationDetails can only have up to 5 actions', + ); + } + if (inputs.length > 5) { + throw ArgumentError( + 'WindowsNotificationDetails can only have up to 5 inputs', + ); + } + builder.element( + 'actions', + nest: () { + for (final WindowsInput input in inputs) { + switch (input) { + case WindowsTextInput(): + input.buildXml(builder); + case WindowsSelectionInput(): + input.buildXml(builder); + } + } + for (final WindowsAction action in actions) { + action.buildXml(builder); + } + }, + ); + audio?.buildXml(builder); + header?.buildXml(builder); + } + + /// Generates the `` element of the notification. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-binding + void generateBinding(XmlBuilder builder) { + if (subtitle != null) { + builder.element('text', nest: subtitle); + } + for (final WindowsImage image in images) { + image.buildXml(builder); + } + for (final WindowsRow row in rows) { + row.buildXml(builder); + } + for (final WindowsProgressBar progressBar in progressBars) { + progressBar.buildXml(builder); + } + } + + /// XML attributes for the toast notification as a whole. + Map get attributes => { + if (duration != null) 'duration': duration!.name, + if (timestamp != null) + 'displayTimestamp': timestamp!.toIso8601StringTz(), + if (scenario != null) 'scenario': scenario!.name, + }; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/header.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/header.dart new file mode 100755 index 00000000..b7de790d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/header.dart @@ -0,0 +1,19 @@ +import 'package:xml/xml.dart'; + +import '../notification_header.dart'; + +/// Converts a [WindowsHeader] to XML +extension HeaderToXml on WindowsHeader { + /// Serializes this header to XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-header + void buildXml(XmlBuilder builder) => builder.element( + 'header', + attributes: { + 'id': id, + 'title': title, + 'arguments': arguments, + if (activation != null) 'activationType': activation!.name, + }, + ); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/image.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/image.dart new file mode 100755 index 00000000..cbf86965 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/image.dart @@ -0,0 +1,22 @@ +import 'package:xml/xml.dart'; + +import '../notification_parts.dart'; + +/// Converts a [WindowsImage] to XML +extension ImageToXml on WindowsImage { + /// Serializes this image to Windows-compatible XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-image + void buildXml(XmlBuilder builder) { + builder.element( + 'image', + attributes: { + 'src': uri.toString(), + 'alt': altText, + 'addImageQuery': addQueryParams.toString(), + if (placement != null) 'placement': placement!.name, + if (crop != null) 'hint-crop': crop!.name, + }, + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/input.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/input.dart new file mode 100755 index 00000000..407421a5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/input.dart @@ -0,0 +1,55 @@ +import 'package:xml/xml.dart'; + +import '../notification_input.dart'; + +/// Converts a [WindowsTextInput] to XML +extension TextInputToXml on WindowsTextInput { + /// Serializes this input to Windows-compatible XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-input + void buildXml(XmlBuilder builder) => builder.element( + 'input', + attributes: { + 'id': id, + 'type': type.name, + if (title != null) 'title': title!, + if (placeHolderContent != null) + 'placeHolderContent': placeHolderContent!, + }, + ); +} + +/// Converts a [WindowsSelectionInput] to XML +extension SelectionInputToXml on WindowsSelectionInput { + /// Serializes this input to Windows-compatible XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-input + void buildXml(XmlBuilder builder) => builder.element( + 'input', + attributes: { + 'id': id, + 'type': type.name, + if (title != null) 'title': title!, + if (defaultItem != null) 'defaultInput': defaultItem!, + }, + nest: () { + for (final WindowsSelection item in items) { + item.buildXml(builder); + } + }, + ); +} + +/// Converts a [WindowsSelection] to XML +extension SelectionToXml on WindowsSelection { + /// Serializes this selection to Windows-compatible XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-selection + void buildXml(XmlBuilder builder) => builder.element( + 'selection', + attributes: { + 'id': id, + 'content': content, + }, + ); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/progress.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/progress.dart new file mode 100755 index 00000000..ee8ef441 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/progress.dart @@ -0,0 +1,30 @@ +import 'package:xml/xml.dart'; + +import '../notification_progress.dart'; + +/// Converts a [WindowsProgressBar] to XML +extension ProgressBarToXml on WindowsProgressBar { + /// Serializes this progress bar to Windows-compatible XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-progress + void buildXml(XmlBuilder builder) => builder.element( + 'progress', + attributes: { + 'status': status, + 'value': '{$id-progressValue}', + if (title != null) 'title': title!, + if (label != null) 'valueStringOverride': '{$id-progressString}', + }, + ); + + /// The data bindings for this progress bar. + /// + /// To support dynamic updates, [buildXml] will inject placeholder strings + /// called data bindings instead of actual values. This can then be updated + /// dynamically later by calling + /// [FlutterLocalNotificationsWindows.updateProgressBar]. + Map get data => { + '$id-progressValue': value?.toString() ?? 'indeterminate', + if (label != null) '$id-progressString': label!, + }; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/row.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/row.dart new file mode 100755 index 00000000..cada3be4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/row.dart @@ -0,0 +1,35 @@ +import 'package:xml/xml.dart'; + +import '../notification_parts.dart'; +import '../notification_row.dart'; + +import 'image.dart'; +import 'text.dart'; + +/// Converts a [WindowsRow] to XML +extension RowToXml on WindowsRow { + /// Serializes this group to XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-group + void buildXml(XmlBuilder builder) => builder.element( + 'group', + nest: () { + for (final WindowsColumn column in columns) { + builder.element( + 'subgroup', + attributes: {'hint-weight': '1'}, + nest: () { + for (final WindowsNotificationPart part in column.parts) { + switch (part) { + case WindowsImage(): + part.buildXml(builder); + case WindowsNotificationText(): + part.buildXml(builder); + } + } + }, + ); + } + }, + ); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/text.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/text.dart new file mode 100755 index 00000000..419e6642 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/details/xml/text.dart @@ -0,0 +1,21 @@ +import 'package:xml/xml.dart'; + +import '../notification_parts.dart'; + +/// Converts a [WindowsNotificationText] to XML +extension TextToXml on WindowsNotificationText { + /// Serializes this text to Windows-compatible XML. + /// + /// See: https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/element-text + void buildXml(XmlBuilder builder) => builder.element( + 'text', + attributes: { + if (languageCode != null) 'lang': languageCode!, + if (placement != null) 'placement': placement!.name, + 'hint-callScenarioCenterAlign': centerIfCall.toString(), + 'hint-align': 'center', + if (isCaption) 'hint-style': 'captionsubtle', + }, + nest: text, + ); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/ffi/bindings.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/ffi/bindings.dart new file mode 100755 index 00000000..47567048 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/ffi/bindings.dart @@ -0,0 +1,384 @@ +// ignore_for_file: always_specify_types +// ignore_for_file: camel_case_types +// ignore_for_file: non_constant_identifier_names + +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +// ignore_for_file: type=lint +import 'dart:ffi' as ffi; +import 'package:ffi/ffi.dart' as pkg_ffi; + +/// Bindings for `src/ffi_api.h`. +/// +/// Regenerate bindings with `dart run ffigen --config ffigen.yaml`. +/// +class NotificationsPluginBindings { + /// Holds the symbol lookup function. + final ffi.Pointer Function(String symbolName) + _lookup; + + /// The symbols are looked up in [dynamicLibrary]. + NotificationsPluginBindings(ffi.DynamicLibrary dynamicLibrary) + : _lookup = dynamicLibrary.lookup; + + /// The symbols are looked up with [lookup]. + NotificationsPluginBindings.fromLookup( + ffi.Pointer Function(String symbolName) + lookup) + : _lookup = lookup; + + /// Checks whether the current application has package identity. + /// + /// This impacts whether apps can query active notifications or cancel them. + /// For more details, see + /// https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/package-identity-overview. + bool hasPackageIdentity() { + return _hasPackageIdentity(); + } + + late final _hasPackageIdentityPtr = + _lookup>('hasPackageIdentity'); + late final _hasPackageIdentity = + _hasPackageIdentityPtr.asFunction(); + + bool isValidXml( + ffi.Pointer xml, + ) { + return _isValidXml( + xml, + ); + } + + late final _isValidXmlPtr = + _lookup)>>( + 'isValidXml'); + late final _isValidXml = + _isValidXmlPtr.asFunction)>(); + + /// Allocates a new plugin that must be released with [disposePlugin]. + ffi.Pointer createPlugin() { + return _createPlugin(); + } + + late final _createPluginPtr = + _lookup Function()>>( + 'createPlugin'); + late final _createPlugin = + _createPluginPtr.asFunction Function()>(); + + /// Releases the plugin and any resources it was holding onto. + void disposePlugin( + ffi.Pointer ptr, + ) { + return _disposePlugin( + ptr, + ); + } + + late final _disposePluginPtr = + _lookup)>>( + 'disposePlugin'); + late final _disposePlugin = + _disposePluginPtr.asFunction)>(); + + /// Initializes the plugin and registers the callback to be run when a notification is pressed. + bool init( + ffi.Pointer plugin, + ffi.Pointer appName, + ffi.Pointer aumId, + ffi.Pointer guid, + ffi.Pointer iconPath, + NativeNotificationCallback callback, + ) { + return _init( + plugin, + appName, + aumId, + guid, + iconPath, + callback, + ); + } + + late final _initPtr = _lookup< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + NativeNotificationCallback)>>('init'); + late final _init = _initPtr.asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + NativeNotificationCallback)>(); + + /// Shows the XML as a notification with the given ID. See [updateNotification] for details on + /// bindings. + bool showNotification( + ffi.Pointer plugin, + int id, + ffi.Pointer xml, + NativeStringMap bindings, + ) { + return _showNotification( + plugin, + id, + xml, + bindings, + ); + } + + late final _showNotificationPtr = _lookup< + ffi.NativeFunction< + ffi.Bool Function(ffi.Pointer, ffi.Int, + ffi.Pointer, NativeStringMap)>>('showNotification'); + late final _showNotification = _showNotificationPtr.asFunction< + bool Function(ffi.Pointer, int, ffi.Pointer, + NativeStringMap)>(); + + /// Schedules the notification to be shown at the given time (as a [time_t]). + bool scheduleNotification( + ffi.Pointer plugin, + int id, + ffi.Pointer xml, + int time, + ) { + return _scheduleNotification( + plugin, + id, + xml, + time, + ); + } + + late final _scheduleNotificationPtr = _lookup< + ffi.NativeFunction< + ffi.Bool Function(ffi.Pointer, ffi.Int, + ffi.Pointer, ffi.Int)>>('scheduleNotification'); + late final _scheduleNotification = _scheduleNotificationPtr.asFunction< + bool Function( + ffi.Pointer, int, ffi.Pointer, int)>(); + + /// Updates a notification with the provided bindings after it's been shown. + /// + /// String values in the `` element of the XML can be placeholders instead of values, + /// for example, `{name}` and then call this function with a map with a `name` key, + /// and any string value, and the notification will be updated with that value where `name` was. + NativeUpdateResult updateNotification( + ffi.Pointer plugin, + int id, + NativeStringMap bindings, + ) { + return NativeUpdateResult.fromValue(_updateNotification( + plugin, + id, + bindings, + )); + } + + late final _updateNotificationPtr = _lookup< + ffi.NativeFunction< + ffi.UnsignedInt Function(ffi.Pointer, ffi.Int, + NativeStringMap)>>('updateNotification'); + late final _updateNotification = _updateNotificationPtr.asFunction< + int Function(ffi.Pointer, int, NativeStringMap)>(); + + /// Cancels all notifications. + void cancelAll( + ffi.Pointer plugin, + ) { + return _cancelAll( + plugin, + ); + } + + late final _cancelAllPtr = + _lookup)>>( + 'cancelAll'); + late final _cancelAll = + _cancelAllPtr.asFunction)>(); + + /// Cancels a notification with the given ID. + /// + /// Only applications with "package identity" (ie, installed with an MSIX installer), can use this. + void cancelNotification( + ffi.Pointer plugin, + int id, + ) { + return _cancelNotification( + plugin, + id, + ); + } + + late final _cancelNotificationPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, ffi.Int)>>('cancelNotification'); + late final _cancelNotification = _cancelNotificationPtr + .asFunction, int)>(); + + /// Gets all notifications that have already been shown but are still in the Action center. + /// + /// Only applications with "package identity" (ie, installed with an MSIX installer), can use this. + /// When your app does not have identity, such as in debug mode, this will return an empty array. + ffi.Pointer getActiveNotifications( + ffi.Pointer plugin, + ffi.Pointer size, + ) { + return _getActiveNotifications( + plugin, + size, + ); + } + + late final _getActiveNotificationsPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer)>>('getActiveNotifications'); + late final _getActiveNotifications = _getActiveNotificationsPtr.asFunction< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>(); + + /// Gets all notifications that have been scheduled but not yet shown. + ffi.Pointer getPendingNotifications( + ffi.Pointer plugin, + ffi.Pointer size, + ) { + return _getPendingNotifications( + plugin, + size, + ); + } + + late final _getPendingNotificationsPtr = _lookup< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer)>>('getPendingNotifications'); + late final _getPendingNotifications = _getPendingNotificationsPtr.asFunction< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>(); + + /// Releases the memory associated with a [NativeNotificationDetails] array. + void freeDetailsArray( + ffi.Pointer ptr, + ) { + return _freeDetailsArray( + ptr, + ); + } + + late final _freeDetailsArrayPtr = _lookup< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer)>>('freeDetailsArray'); + late final _freeDetailsArray = _freeDetailsArrayPtr + .asFunction)>(); + + /// Releases the memory associated with a [NativeLaunchDetails]. + void freeLaunchDetails( + NativeLaunchDetails details, + ) { + return _freeLaunchDetails( + details, + ); + } + + late final _freeLaunchDetailsPtr = + _lookup>( + 'freeLaunchDetails'); + late final _freeLaunchDetails = + _freeLaunchDetailsPtr.asFunction(); +} + +final class NativePlugin extends ffi.Opaque {} + +/// A key-value pair in a map where both the keys and values are strings. +final class StringMapEntry extends ffi.Struct { + external ffi.Pointer key; + + external ffi.Pointer value; +} + +/// A map where the keys and values are all strings. +final class NativeStringMap extends ffi.Struct { + external ffi.Pointer entries; + + @ffi.Int() + external int size; +} + +/// Details about a notification. +final class NativeNotificationDetails extends ffi.Struct { + @ffi.Int() + external int id; +} + +/// How the app was launched, either by pressing on the notification or an action within it. +enum NativeLaunchType { + notification(0), + action(1); + + final int value; + const NativeLaunchType(this.value); + + static NativeLaunchType fromValue(int value) => switch (value) { + 0 => notification, + 1 => action, + _ => throw ArgumentError("Unknown value for NativeLaunchType: $value"), + }; +} + +/// Details about how the app was launched. +final class NativeLaunchDetails extends ffi.Struct { + /// Whether the app was launched by a notification + @ffi.Bool() + external bool didLaunch; + + /// What part of the notification launched the app. + @ffi.UnsignedInt() + external int launchType; + + /// The payload sent to the app by the notification. Usually the action that was pressed. + external ffi.Pointer payload; + + /// The IDs and values of any text inputs in the notification. + external NativeStringMap data; +} + +/// See: https://learn.microsoft.com/en-us/uwp/api/windows.ui.notifications.notificationupdateresult +enum NativeUpdateResult { + success(0), + failed(1), + notFound(2); + + final int value; + const NativeUpdateResult(this.value); + + static NativeUpdateResult fromValue(int value) => switch (value) { + 0 => success, + 1 => failed, + 2 => notFound, + _ => + throw ArgumentError("Unknown value for NativeUpdateResult: $value"), + }; +} + +/// A callback that is run with [NativeLaunchDetails] when a notification is pressed. +/// +/// This may be called at app launch or even while the app is running. +typedef NativeNotificationCallback + = ffi.Pointer>; +typedef NativeNotificationCallbackFunction = ffi.Void Function( + NativeLaunchDetails details); +typedef DartNativeNotificationCallbackFunction = void Function( + NativeLaunchDetails details); diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/ffi/utils.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/ffi/utils.dart new file mode 100755 index 00000000..3a63be14 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/ffi/utils.dart @@ -0,0 +1,75 @@ +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; +import 'package:flutter_local_notifications_platform_interface/flutter_local_notifications_platform_interface.dart'; + +import '../details.dart'; +import '../plugin/base.dart'; +import 'bindings.dart'; + +/// Helpful methods on native string maps. +extension NativeStringMapUtils on NativeStringMap { + /// Converts this map to a typical Dart map. + Map toMap() => { + for (int index = 0; index < size; index++) + entries[index].key.toDartString(): + entries[index].value.toDartString(), + }; +} + +/// Gets the [NotificationResponseType] from a [NativeLaunchType]. +NotificationResponseType getResponseType(int launchType) { + switch (NativeLaunchType.fromValue(launchType)) { + case NativeLaunchType.notification: + return NotificationResponseType.selectedNotification; + case NativeLaunchType.action: + return NotificationResponseType.selectedNotificationAction; + } +} + +/// Gets the [NotificationUpdateResult] from a [NativeUpdateResult]. +NotificationUpdateResult getUpdateResult(NativeUpdateResult result) { + switch (result) { + case NativeUpdateResult.success: + return NotificationUpdateResult.success; + case NativeUpdateResult.failed: + return NotificationUpdateResult.error; + case NativeUpdateResult.notFound: + return NotificationUpdateResult.notFound; + } +} + +/// Helpful methods on string maps. +extension MapToNativeMap on Map { + /// Allocates a [NativeStringMap] using the provided arena. + NativeStringMap toNativeMap(Arena arena) { + final Pointer pointer = arena(); + pointer.ref.size = length; + pointer.ref.entries = arena(length); + int index = 0; + for (final MapEntry entry in entries) { + pointer.ref.entries[index].key = entry.key.toNativeUtf8(allocator: arena); + pointer.ref.entries[index].value = + entry.value.toNativeUtf8(allocator: arena); + index++; + } + return pointer.ref; + } +} + +/// Helpful methods on native notification details. +extension NativeNotificationDetailsUtils on Pointer { + /// Parses this array as a list of [ActiveNotification]s. + List asActiveNotifications(int length) => + [ + for (int index = 0; index < length; index++) + ActiveNotification(id: this[index].id), + ]; + + /// Parses this array os a list of [PendingNotificationRequest]s. + List asPendingRequests(int length) => + [ + for (int index = 0; index < length; index++) + PendingNotificationRequest(this[index].id, null, null, null), + ]; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/msix/ffi.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/msix/ffi.dart new file mode 100755 index 00000000..a80eb122 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/msix/ffi.dart @@ -0,0 +1,50 @@ +import 'dart:ffi'; +import 'dart:io'; + +import '../../flutter_local_notifications_windows.dart'; +import '../ffi/bindings.dart'; + +/// Helpful methods to support MSIX and package identity. +class MsixUtils { + /// Returns whether the current app was installed with an MSIX installer. + /// + /// Using an MSIX grants your application [package identity](https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/package-identity-overview), + /// which allows it to use [certain APIs](https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/modernize-packaged-apps). + /// + /// Specifically, using an MSIX installer allows your app to: + /// - use [FlutterLocalNotificationsWindows.getActiveNotifications] + /// - use [FlutterLocalNotificationsWindows.cancel] + /// - use custom files for notification sounds + /// - use network sources for notifications + /// - use `ms-appx:///` URIs for resources + /// + /// These functions will simply do nothing or return empty data in apps + /// without package identity. Additionally: + /// - [WindowsImage.getAssetUri] will return a `file:///` or `ms-appx:///` URI, + /// depending on whether the app is running in debug, release, or as an MSIX. + /// - [WindowsNotificationAudio.asset] takes an audio file to use for apps + /// with package identity, and a preset fallbacks for apps without. + static bool hasPackageIdentity() { + final bool? cached = _hasPackageIdentity; + if (cached != null) { + return cached; + } else if (!Platform.isWindows) { + return false; + } else { + final DynamicLibrary lib = DynamicLibrary.open( + 'flutter_local_notifications_windows.dll', + ); + final NotificationsPluginBindings bindings = + NotificationsPluginBindings(lib); + final bool result = bindings.hasPackageIdentity(); + _hasPackageIdentity = result; + return result; + } + } + + static bool? _hasPackageIdentity; + + /// Returns an `ms-appx:///` URI from a [Flutter asset](https://docs.flutter.dev/ui/assets/assets-and-images). + static Uri getAssetUri(String path) => + Uri.parse('ms-appx:///data/flutter_assets/$path'); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/msix/stub.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/msix/stub.dart new file mode 100755 index 00000000..49f148a8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/msix/stub.dart @@ -0,0 +1,28 @@ +import '../../flutter_local_notifications_windows.dart'; + +/// Helpful methods to support MSIX and package identity. +class MsixUtils { + /// Returns whether the current app was installed with an MSIX installer. + /// + /// Using an MSIX grants your application [package identity](https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/package-identity-overview), + /// which allows it to use [certain APIs](https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/modernize-packaged-apps). + /// + /// Specifically, using an MSIX installer allows your app to: + /// - use [FlutterLocalNotificationsWindows.getActiveNotifications] + /// - use [FlutterLocalNotificationsWindows.cancel] + /// - use custom files for notification sounds + /// - use network sources for notifications + /// - use `ms-appx:///` URIs for resources + /// + /// These functions will simply do nothing or return empty data in apps + /// without package identity. Additionally: + /// - [WindowsImage.getAssetUri] will return a `file:///` or `ms-appx:///` URI, + /// depending on whether the app is running in debug, release, or as an MSIX. + /// - [WindowsNotificationAudio.asset] takes an audio file to use for apps + /// with package identity, and a preset fallbacks for apps without. + static bool hasPackageIdentity() => false; // platforms without FFI + + /// Gets an `ms-appx:///` URI from a [Flutter asset](https://docs.flutter.dev/ui/assets/assets-and-images). + static Uri getAssetUri(String path) => + Uri.parse('ms-appx:///data/flutter_assets/$path'); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/plugin/base.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/plugin/base.dart new file mode 100755 index 00000000..96df1271 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/plugin/base.dart @@ -0,0 +1,89 @@ +import 'package:flutter_local_notifications_platform_interface/flutter_local_notifications_platform_interface.dart'; +import 'package:timezone/timezone.dart'; + +import '../details.dart'; +import '../details/xml/progress.dart'; + +export 'package:flutter_local_notifications_platform_interface/flutter_local_notifications_platform_interface.dart'; +export 'package:timezone/timezone.dart'; + +/// The Windows implementation of `package:flutter_local_notifications`. +abstract class WindowsNotificationsBase + extends FlutterLocalNotificationsPlatform { + /// Initializes the plugin. No other method should be called before this. + Future initialize( + WindowsInitializationSettings settings, { + DidReceiveNotificationResponseCallback? onNotificationReceived, + }); + + /// Releases any resources used by this plugin. + void dispose(); + + /// Shows a notification using raw XML passed to the Windows APIs. + /// + /// To check if the XML is valid, use [isValidXml]. + Future showRawXml({ + required int id, + required String xml, + Map bindings = const {}, + }); + + @override + Future show( + int id, + String? title, + String? body, { + String? payload, + WindowsNotificationDetails? details, + }); + + /// Schedules a notification to appear at the given date and time. + Future zonedSchedule( + int id, + String? title, + String? body, + TZDateTime scheduledDate, + WindowsNotificationDetails? details, { + String? payload, + }); + + /// Schedules a notification to appear using raw XML at this date and time. + /// + /// See https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/schema-root. + /// For validation, see [the Windows Notifications Visualizer](https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/notifications-visualizer). + Future zonedScheduleRawXml( + int id, + String xml, + TZDateTime scheduledDate, + WindowsNotificationDetails? details, + ); + + /// Updates the progress bar in the notification with the given ID. + /// + /// Note that in order to update [WindowsProgressBar.label], it must + /// not have been set to `null` when the notification was created + Future updateProgressBar({ + required int notificationId, + required WindowsProgressBar progressBar, + }) => + updateBindings( + id: notificationId, + bindings: progressBar.data, + ); + + /// Updates any data binding in the given notification. + /// + /// Instead of a text value, you can replace any value in the `` + /// element with `{name}`, and then use this function to update that value + /// by passing `data: {'name': value}`. + Future updateBindings({ + required int id, + required Map bindings, + }); + + /// Checks if some XML is a valid Windows notification. + /// + /// See https://learn.microsoft.com/en-us/uwp/schemas/tiles/toastschema/schema-root. + /// For validation, see [the Windows Notifications Visualizer](https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/notifications-visualizer). + bool isValidXml(String xml); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/plugin/ffi.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/plugin/ffi.dart new file mode 100755 index 00000000..9e13258e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/plugin/ffi.dart @@ -0,0 +1,369 @@ +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import '../details.dart'; +import '../details/notification_to_xml.dart'; +import '../ffi/bindings.dart'; +import '../ffi/utils.dart'; + +import 'base.dart'; + +void _globalLaunchCallback(NativeLaunchDetails details) { + FlutterLocalNotificationsWindows.instance?._onNotificationReceived(details); +} + +extension on String { + bool get isValidGuid => + length == 36 && + this[8] == '-' && + this[13] == '-' && + this[18] == '-' && + this[23] == '-'; +} + +/// The Windows implementation of `package:flutter_local_notifications`. +class FlutterLocalNotificationsWindows extends WindowsNotificationsBase { + /// Creates an instance of the native plugin. + FlutterLocalNotificationsWindows(); + + /// Registers the Windows implementation with Flutter. + static void registerWith() { + FlutterLocalNotificationsPlatform.instance = + FlutterLocalNotificationsWindows(); + } + + /// The global instance of this plugin. Used in [_globalLaunchCallback]. + static FlutterLocalNotificationsWindows? instance; + + /// The FFI generated bindings to the native code. + late final NotificationsPluginBindings _bindings = + NotificationsPluginBindings(_library); + + final DynamicLibrary _library = + DynamicLibrary.open('flutter_local_notifications_windows.dll'); + + /// A pointer to the C++ handler class. + late final Pointer _plugin; + + bool _isReady = false; + + /// The last recorded launch details, if any. + /// + /// If the app is opened with a notification, this can be read with + /// [getNotificationAppLaunchDetails]. If a notification is pressed while the + /// app is running, this will be passed to [userCallback]. + NativeLaunchDetails? _details; + + /// A callback from [initialize] to run when a notification is pressed. + DidReceiveNotificationResponseCallback? userCallback; + + @override + Future initialize( + WindowsInitializationSettings settings, { + DidReceiveNotificationResponseCallback? onNotificationReceived, + }) async => + using((Arena arena) { + if (_isReady) { + return true; + } + _plugin = _bindings.createPlugin(); + // The C++ code will crash if there's an invalid GUID, so check it here + if (!settings.guid.isValidGuid) { + throw ArgumentError.value( + settings.guid, + 'GUID', + 'Invalid GUID. Please use xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' + ' format.\nYou can get one by searching GUID generators online', + ); + } + instance = this; + userCallback = onNotificationReceived; + final Pointer appName = + settings.appName.toNativeUtf8(allocator: arena); + final Pointer aumId = + settings.appUserModelId.toNativeUtf8(allocator: arena); + final Pointer guid = settings.guid.toNativeUtf8(allocator: arena); + final Pointer iconPath = + settings.iconPath?.toNativeUtf8(allocator: arena) ?? nullptr; + final NativeNotificationCallback callback = + NativeCallable.listener( + _globalLaunchCallback, + ).nativeFunction; + final bool result = + _bindings.init(_plugin, appName, aumId, guid, iconPath, callback); + _isReady = result; + return result; + }); + + @override + void dispose() { + if (!_isReady) { + return; + } + _bindings.disposePlugin(_plugin); + instance = null; + _isReady = false; + } + + void _onNotificationReceived(NativeLaunchDetails details) { + if (!_isReady) { + return; + } else if (_details != null) { + _bindings.freeLaunchDetails(_details!); + } + _details = details; + final Map data = details.data.toMap(); + final NotificationResponse response = NotificationResponse( + notificationResponseType: getResponseType(details.launchType), + payload: details.payload.toDartString(), + actionId: details.payload.toDartString(), + data: data, + ); + userCallback?.call(response); + } + + @override + Future cancel(int id) async { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + _bindings.cancelNotification(_plugin, id); + } + + @override + Future cancelAll() async { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + _bindings.cancelAll(_plugin); + } + + @override + Future> getActiveNotifications() async => + using((Arena arena) { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + final Pointer length = arena(); + final Pointer array = + _bindings.getActiveNotifications(_plugin, length); + final List result = + array.asActiveNotifications(length.value); + _bindings.freeDetailsArray(array); + return result; + }); + + @override + Future> + pendingNotificationRequests() async => using((Arena arena) { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + final Pointer length = arena(); + final Pointer array = + _bindings.getPendingNotifications(_plugin, length); + final List result = + array.asPendingRequests(length.value); + _bindings.freeDetailsArray(array); + return result; + }); + + @override + Future + getNotificationAppLaunchDetails() async { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + final NativeLaunchDetails? details = _details; + if (details == null) { + return null; + } + final Map data = details.data.toMap(); + return NotificationAppLaunchDetails( + details.didLaunch, + notificationResponse: NotificationResponse( + notificationResponseType: getResponseType(details.launchType), + payload: details.payload.toDartString(), + actionId: details.payload.toDartString(), + data: data, + ), + ); + } + + @override + Future periodicallyShow( + int id, + String? title, + String? body, + RepeatInterval repeatInterval, + ) async { + throw UnsupportedError( + 'Windows devices cannot periodically show notifications', + ); + } + + @override + Future periodicallyShowWithDuration( + int id, + String? title, + String? body, + Duration repeatDurationInterval, + ) async { + throw UnsupportedError( + 'Windows devices cannot periodically show notifications', + ); + } + + @override + Future show(int id, String? title, String? body, + {String? payload, WindowsNotificationDetails? details}) async => + using((Arena arena) { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + final Map bindings = { + if (details != null) ...details.bindings, + for (final WindowsProgressBar progressBar + in details?.progressBars ?? []) + ...progressBar.data, + }; + final NativeStringMap nativeMap = bindings.toNativeMap(arena); + final String xml = notificationToXml( + title: title, + body: body, + payload: payload, + details: details, + ); + final bool result = _bindings.showNotification( + _plugin, + id, + xml.toNativeUtf8(allocator: arena), + nativeMap, + ); + if (!result) { + throw Exception( + 'Flutter Local Notifications could not show notification', + ); + } + }); + + @override + Future showRawXml({ + required int id, + required String xml, + Map bindings = const {}, + }) async => + using((Arena arena) { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + final bool result = _bindings.showNotification(_plugin, id, + xml.toNativeUtf8(allocator: arena), bindings.toNativeMap(arena)); + if (!result) { + throw ArgumentError('Flutter Local Notifications: Invalid XML'); + } + }); + + @override + bool isValidXml(String xml) => using((Arena arena) { + final Pointer nativeXml = xml.toNativeUtf8(allocator: arena); + return _bindings.isValidXml(nativeXml); + }); + + @override + Future zonedSchedule( + int id, + String? title, + String? body, + TZDateTime scheduledDate, + WindowsNotificationDetails? details, { + String? payload, + }) async => + using((Arena arena) { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + if (scheduledDate.isBefore(DateTime.now())) { + throw ArgumentError( + 'Flutter Local Notifications cannot' + ' schedule notifications in the past', + ); + } + final String xml = notificationToXml( + title: title, + body: body, + payload: payload, + details: details, + ); + final int secondsSinceEpoch = + scheduledDate.millisecondsSinceEpoch ~/ 1000; + _bindings.scheduleNotification( + _plugin, + id, + xml.toNativeUtf8(allocator: arena), + secondsSinceEpoch, + ); + }); + + @override + Future zonedScheduleRawXml( + int id, + String xml, + TZDateTime scheduledDate, + WindowsNotificationDetails? details, + ) async => + using((Arena arena) { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + if (scheduledDate.isBefore(DateTime.now())) { + throw ArgumentError( + 'Flutter Local Notifications cannot' + ' schedule notifications in the past', + ); + } + final int secondsSinceEpoch = + scheduledDate.millisecondsSinceEpoch ~/ 1000; + _bindings.scheduleNotification( + _plugin, + id, + xml.toNativeUtf8(allocator: arena), + secondsSinceEpoch, + ); + }); + + @override + Future updateBindings({ + required int id, + required Map bindings, + }) async => + using((Arena arena) { + if (!_isReady) { + throw StateError( + 'Flutter Local Notifications must be initialized before use', + ); + } + final NativeUpdateResult result = _bindings.updateNotification( + _plugin, id, bindings.toNativeMap(arena)); + return getUpdateResult(result); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/plugin/stub.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/plugin/stub.dart new file mode 100755 index 00000000..9fc1aeef --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/lib/src/plugin/stub.dart @@ -0,0 +1,96 @@ +import '../details.dart'; +import 'base.dart'; + +/// The Windows implementation of `package:flutter_local_notifications`. +class FlutterLocalNotificationsWindows extends WindowsNotificationsBase { + @override + Future initialize( + WindowsInitializationSettings settings, { + DidReceiveNotificationResponseCallback? onNotificationReceived, + }) async { + throw UnsupportedError( + 'This platform does not support Windows notifications', + ); + } + + @override + void dispose() {} + + @override + Future cancel(int id) async {} + + @override + Future cancelAll() async {} + + @override + Future> getActiveNotifications() async => + []; + + @override + Future + getNotificationAppLaunchDetails() async => null; + + @override + Future> + pendingNotificationRequests() async => []; + + @override + Future periodicallyShow( + int id, + String? title, + String? body, + RepeatInterval repeatInterval, + ) async {} + + @override + Future periodicallyShowWithDuration( + int id, + String? title, + String? body, + Duration repeatDurationInterval, + ) async {} + + @override + Future show( + int id, + String? title, + String? body, { + String? payload, + WindowsNotificationDetails? details, + }) async {} + + @override + Future showRawXml({ + required int id, + required String xml, + Map bindings = const {}, + }) async {} + + @override + Future zonedSchedule( + int id, + String? title, + String? body, + TZDateTime scheduledDate, + WindowsNotificationDetails? details, { + String? payload, + }) async {} + + @override + Future zonedScheduleRawXml( + int id, + String xml, + TZDateTime scheduledDate, + WindowsNotificationDetails? details, + ) async {} + + @override + Future updateBindings({ + required int id, + required Map bindings, + }) async => + NotificationUpdateResult.success; + + @override + bool isValidXml(String xml) => false; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/pubspec.yaml new file mode 100755 index 00000000..0e623cca --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/pubspec.yaml @@ -0,0 +1,30 @@ +name: flutter_local_notifications_windows +description: Windows implementation of the flutter_local_notifications plugin +version: 1.0.3 +homepage: https://github.com/MaikuB/flutter_local_notifications/tree/master/flutter_local_notifications_windows +issue_tracker: https://github.com/MaikuB/flutter_local_notifications/issues + +environment: + sdk: ^3.4.0 + flutter: ">=3.22.0" + +dependencies: + flutter: + sdk: flutter + ffi: ^2.1.2 + flutter_local_notifications_platform_interface: ^9.0.0 + meta: ^1.11.0 + timezone: ^0.10.0 + xml: ^6.5.0 + +dev_dependencies: + ffigen: ^13.0.0 + test: ^1.25.2 + +flutter: + plugin: + implements: flutter_local_notifications + platforms: + windows: + ffiPlugin: true + dartPluginClass: FlutterLocalNotificationsWindows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/CMakeLists.txt new file mode 100755 index 00000000..5a95e858 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/CMakeLists.txt @@ -0,0 +1,21 @@ +# The Flutter tooling requires that developers have CMake 3.10 or later +# installed. You should not increase this version, as doing so will cause +# the plugin to fail to compile for some customers of the plugin. +cmake_minimum_required(VERSION 3.10) + +project(flutter_local_notifications_windows_library VERSION 1.0.0 LANGUAGES CXX) + +add_library(flutter_local_notifications_windows SHARED + "ffi_api.cpp" + "plugin.cpp" + "utils.cpp" +) + +target_compile_features(flutter_local_notifications_windows PRIVATE cxx_std_17) + +set_target_properties(flutter_local_notifications_windows PROPERTIES + PUBLIC_HEADER ffi_api.h + OUTPUT_NAME "flutter_local_notifications_windows" +) + +target_compile_definitions(flutter_local_notifications_windows PUBLIC DART_SHARED_LIB) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/ffi_api.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/ffi_api.cpp new file mode 100755 index 00000000..df4e4cb1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/ffi_api.cpp @@ -0,0 +1,160 @@ +#include // <-- This must be the first Windows header +#include +#include + +#include "ffi_api.h" +#include "plugin.hpp" +#include "utils.hpp" + +using winrt::Windows::Data::Xml::Dom::XmlDocument; + +bool hasPackageIdentity() { + if (!IsWindows8OrGreater()) return false; + uint32_t length = 0; + int error = GetCurrentPackageFullName(&length, nullptr); + return error != APPMODEL_ERROR_NO_PACKAGE; +} + +NativePlugin* createPlugin() { return new NativePlugin(); } + +void disposePlugin(NativePlugin* plugin) { delete plugin; } + +bool init( + NativePlugin* plugin, char* appName, char* aumId, char* guid, char* iconPath, + NativeNotificationCallback callback +) { + string icon; + if (iconPath != nullptr) icon = string(iconPath); + const auto didRegister = plugin->registerApp(aumId, appName, guid, icon, callback); + if (!didRegister) return false; + plugin->hasIdentity = hasPackageIdentity(); + plugin->aumid = winrt::to_hstring(aumId); + plugin->notifier = plugin->hasIdentity + ? ToastNotificationManager::CreateToastNotifier() + : ToastNotificationManager::CreateToastNotifier(plugin->aumid); + plugin->history = ToastNotificationManager::History(); + plugin->isReady = true; + return true; +} + +bool isValidXml(char* xml) { + XmlDocument doc = XmlDocument(); + try { + doc.LoadXml(winrt::to_hstring(xml)); + return true; + } catch (winrt::hresult_error error) { + return false; + } +} + +bool showNotification(NativePlugin* plugin, int id, char* xml, NativeStringMap bindings) { + if (!plugin->isReady) return false; + XmlDocument doc; + try { + doc.LoadXml(winrt::to_hstring(xml)); + } catch (winrt::hresult_error error) { + return false; + } + ToastNotification notification(doc); + const auto data = dataFromMap(bindings); + notification.Tag(winrt::to_hstring(id)); + notification.Data(data); + plugin->notifier.value().Show(notification); + return true; +} + +bool scheduleNotification(NativePlugin* plugin, int id, char* xml, int time) { + if (!plugin->isReady) return false; + XmlDocument doc; + try { + doc.LoadXml(winrt::to_hstring(xml)); + } catch (winrt::hresult_error error) { + return false; + } + ScheduledToastNotification notification(doc, winrt::clock::from_time_t(time)); + notification.Tag(winrt::to_hstring(id)); + plugin->notifier.value().AddToSchedule(notification); + return true; +} + +NativeUpdateResult updateNotification(NativePlugin* plugin, int id, NativeStringMap bindings) { + if (!plugin->isReady) return NativeUpdateResult::failed; + const auto tag = winrt::to_hstring(id); + const auto data = dataFromMap(bindings); + const auto result = plugin->notifier.value().Update(data, tag); + return (NativeUpdateResult) result; +} + +void cancelAll(NativePlugin* plugin) { + if (!plugin->isReady) return; + if (plugin->hasIdentity) { + plugin->history.value().Clear(); + } else { + plugin->history.value().Clear(plugin->aumid); + } + for (const auto notification : plugin->notifier.value().GetScheduledToastNotifications()) { + plugin->notifier.value().RemoveFromSchedule(notification); + } +} + +void cancelNotification(NativePlugin* plugin, int id) { + if (!plugin->isReady) return; + const auto tag = winrt::to_hstring(id); + if (plugin->hasIdentity) plugin->history.value().Remove(tag); + for (const auto notification : plugin->notifier.value().GetScheduledToastNotifications()) { + if (notification.Tag() == tag) { + plugin->notifier.value().RemoveFromSchedule(notification); + return; + } + } +} + +NativeNotificationDetails* getActiveNotifications(NativePlugin* plugin, int* size) { + // TODO: Get more details here + if (!plugin->isReady || !plugin->hasIdentity) { + *size = 0; + return nullptr; + } + const auto active = plugin->history.value().GetHistory(); + *size = active.Size(); + const auto result = new NativeNotificationDetails[*size]; + int index = 0; + for (const auto notification : active) { + const auto tag = notification.Tag(); + const auto tagStr = winrt::to_string(tag); + const auto tagInt = std::stoi(tagStr); + result[index++].id = tagInt; + } + return result; +} + +NativeNotificationDetails* getPendingNotifications(NativePlugin* plugin, int* size) { + // TODO: Get more details here + if (!plugin->isReady) { + *size = 0; + return nullptr; + } + const auto pending = plugin->notifier.value().GetScheduledToastNotifications(); + *size = pending.Size(); + const auto result = new NativeNotificationDetails[*size]; + int index = 0; + for (const auto notification : pending) { + const auto tag = notification.Tag(); + const auto tagStr = winrt::to_string(tag); + const auto tagInt = std::stoi(tagStr); + result[index++].id = tagInt; + } + return result; +} + +void freeDetailsArray(NativeNotificationDetails* ptr) { delete[] ptr; } + +void freeLaunchDetails(NativeLaunchDetails details) { + if (details.payload != nullptr) delete[] details.payload; + for (int index = 0; index < details.data.size; index++) { + const auto pair = details.data.entries[index]; + delete pair.key; + delete pair.value; + } + if (details.data.entries != nullptr) delete[] details.data.entries; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/ffi_api.h b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/ffi_api.h new file mode 100755 index 00000000..b2cfe4d7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/ffi_api.h @@ -0,0 +1,143 @@ +#ifndef FFI_API_H_ +#define FFI_API_H_ + +#if _WIN32 +#include +#else +#include +#include +#endif + +#if _WIN32 +#define FFI_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FFI_PLUGIN_EXPORT +#endif + +// FFI needs to use a C-compatible API, even if the code is implemented in C++ or another language. +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/// A fake type to represent the C++ class that will own the Windows API handles. +typedef struct NativePlugin NativePlugin; + +/// A key-value pair in a map where both the keys and values are strings. +typedef struct StringMapEntry { + const char* key; + const char* value; +} StringMapEntry; + +/// A map where the keys and values are all strings. +typedef struct NativeStringMap { + const StringMapEntry* entries; + int size; +} NativeStringMap; + +/// Details about a notification. +typedef struct NativeNotificationDetails { + int id; +} NativeNotificationDetails; + +/// How the app was launched, either by pressing on the notification or an action within it. +typedef enum NativeLaunchType { + notification, + action, +} NativeLaunchType; + +/// Details about how the app was launched. +typedef struct NativeLaunchDetails { + /// Whether the app was launched by a notification + bool didLaunch; + /// What part of the notification launched the app. + NativeLaunchType launchType; + /// The payload sent to the app by the notification. Usually the action that was pressed. + const char* payload; + /// The IDs and values of any text inputs in the notification. + NativeStringMap data; +} NativeLaunchDetails; + +/// A callback that is run with [NativeLaunchDetails] when a notification is pressed. +/// +/// This may be called at app launch or even while the app is running. +typedef void (*NativeNotificationCallback)(NativeLaunchDetails details); + +// See: https://learn.microsoft.com/en-us/uwp/api/windows.ui.notifications.notificationupdateresult +typedef enum NativeUpdateResult { + success = 0, + failed = 1, + notFound = 2, +} NativeUpdateResult; + +/// Checks whether the current application has package identity. +/// +/// This impacts whether apps can query active notifications or cancel them. +/// For more details, see +/// https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/package-identity-overview. +FFI_PLUGIN_EXPORT bool hasPackageIdentity(); + +FFI_PLUGIN_EXPORT bool isValidXml(char* xml); + +/// Allocates a new plugin that must be released with [disposePlugin]. +FFI_PLUGIN_EXPORT NativePlugin* createPlugin(); + +/// Releases the plugin and any resources it was holding onto. +FFI_PLUGIN_EXPORT void disposePlugin(NativePlugin* ptr); + +/// Initializes the plugin and registers the callback to be run when a notification is pressed. +FFI_PLUGIN_EXPORT bool init( + NativePlugin* plugin, char* appName, char* aumId, char* guid, char* iconPath, + NativeNotificationCallback callback +); + +/// Shows the XML as a notification with the given ID. See [updateNotification] for details on +/// bindings. +FFI_PLUGIN_EXPORT bool showNotification( + NativePlugin* plugin, int id, char* xml, NativeStringMap bindings +); + +/// Schedules the notification to be shown at the given time (as a [time_t]). +FFI_PLUGIN_EXPORT bool scheduleNotification(NativePlugin* plugin, int id, char* xml, int time); + +/// Updates a notification with the provided bindings after it's been shown. +/// +/// String values in the `` element of the XML can be placeholders instead of values, +/// for example, `{name}` and then call this function with a map with a `name` key, +/// and any string value, and the notification will be updated with that value where `name` was. +FFI_PLUGIN_EXPORT NativeUpdateResult +updateNotification(NativePlugin* plugin, int id, NativeStringMap bindings); + +/// Cancels all notifications. +FFI_PLUGIN_EXPORT void cancelAll(NativePlugin* plugin); + +/// Cancels a notification with the given ID. +/// +/// Only applications with "package identity" (ie, installed with an MSIX installer), can use this. +FFI_PLUGIN_EXPORT void cancelNotification(NativePlugin* plugin, int id); + +/// Gets all notifications that have already been shown but are still in the Action center. +/// +/// Only applications with "package identity" (ie, installed with an MSIX installer), can use this. +/// When your app does not have identity, such as in debug mode, this will return an empty array. +FFI_PLUGIN_EXPORT NativeNotificationDetails* getActiveNotifications( + NativePlugin* plugin, int* size +); + +/// Gets all notifications that have been scheduled but not yet shown. +FFI_PLUGIN_EXPORT NativeNotificationDetails* getPendingNotifications( + NativePlugin* plugin, int* size +); + +/// Releases the memory associated with a [NativeNotificationDetails] array. +FFI_PLUGIN_EXPORT void freeDetailsArray(NativeNotificationDetails* ptr); + +/// Releases the memory associated with a [NativeLaunchDetails]. +FFI_PLUGIN_EXPORT void freeLaunchDetails(NativeLaunchDetails details); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/plugin.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/plugin.cpp new file mode 100755 index 00000000..45b32204 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/plugin.cpp @@ -0,0 +1,182 @@ +#include + +#include // <-- This must be the first Windows header +#include +#include +#include +#include + +#include "plugin.hpp" +#include "utils.hpp" + +struct RegistryHandle { + using type = HKEY; + + static void close(type value) noexcept { WINRT_VERIFY_(ERROR_SUCCESS, RegCloseKey(value)); } + + static constexpr type invalid() noexcept { return nullptr; } +}; + +using RegistryKey = winrt::handle_type; + +/// This callback will be called when a notification sent by this plugin is clicked on. +struct NotificationActivationCallback : + winrt::implements { + NativeNotificationCallback callback; + + HRESULT __stdcall Activate( + LPCWSTR app, LPCWSTR args, NOTIFICATION_USER_INPUT_DATA const* data, ULONG count + ) noexcept final { + try { + // Fill the data map + vector entries; + for (ULONG i = 0; i < count; i++) { + auto item = data[i]; + const std::string key = CW2A(item.Key, CP_UTF8); + const std::string value = CW2A(item.Value, CP_UTF8); + const auto pair = StringMapEntry {toNativeString(key), toNativeString(value)}; + entries.push_back(pair); + } + + const auto openedWithAction = args != nullptr; + const auto payload = string(CW2A(args, CP_UTF8)); + const auto launchType = + openedWithAction ? NativeLaunchType::action : NativeLaunchType::notification; + NativeLaunchDetails launchDetails; + launchDetails.didLaunch = true; + launchDetails.launchType = launchType; + launchDetails.payload = toNativeString(payload); + launchDetails.data = toNativeMap(entries); + callback(launchDetails); + return S_OK; + } catch (...) { + return winrt::to_hresult(); + } + } +}; + +/// A class factory that creates an instance of NotificationActivationCallback. +struct NotificationActivationCallbackFactory : + winrt::implements { + NativeNotificationCallback callback; + + HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final { + *result = nullptr; + if (outer) return CLASS_E_NOAGGREGATION; + const auto cb = winrt::make_self(); + cb.get()->callback = callback; + return cb->QueryInterface(iid, result); + } + + HRESULT __stdcall LockServer(BOOL) noexcept final { return S_OK; } +}; + +/// Updates the Registry to enable notifications. +/// +/// Related resources: +/// https://docs.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/send-local-toast-other-apps +void UpdateRegistry( + const std::string& aumid, const std::string& appName, const std::string& guid, + const std::optional& iconPath +) { + std::stringstream ss; + ss << "Software\\Microsoft\\Windows\\CurrentVersion\\PushNotifications\\Backup\\" << aumid; + const auto notifSettingsKeyPath = ss.str(); + RegistryKey key; + + // create registry key + // HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\PushNotifications\Backup + winrt::check_win32(RegCreateKeyExA( + HKEY_CURRENT_USER, notifSettingsKeyPath.c_str(), 0, nullptr, 0, KEY_WRITE, nullptr, key.put(), + nullptr + )); + + // put the following key values under the key + // HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\PushNotifications\Backup\ + // + // appType = app:desktop + // Setting = s:banner,s:toast,s:audio,c:toast,c:ringing + // wnsId = NonImmersivePackage + + const std::string appType = "app:desktop"; + const std::string setting = "s:banner,s:toast,s:audio,c:toast,c:ringing"; + const std::string wnsId = "NonImmersivePackage"; + winrt::check_win32(RegSetValueExA( + key.get(), "appType", 0, REG_SZ, reinterpret_cast(appType.c_str()), + static_cast(appType.size() + 1 * sizeof(char)) + )); + winrt::check_win32(RegSetValueExA( + key.get(), "Setting", 0, REG_SZ, reinterpret_cast(setting.c_str()), + static_cast(setting.size() + 1 * sizeof(char)) + )); + winrt::check_win32(RegSetValueExA( + key.get(), "wnsId", 0, REG_SZ, reinterpret_cast(wnsId.c_str()), + static_cast(wnsId.size() + 1 * sizeof(char)) + )); + + // now, we register app info to the Registry. + + ss.clear(); + ss.str(std::string()); + ss << "Software\\Classes\\AppUserModelId\\" << aumid; + const auto appInfoKeyPath = ss.str(); + RegistryKey appInfoKey; + + // create registry key + // HKEY_CURRENT_USER\Software\Classes\AppUserModelId\ + winrt::check_win32(RegCreateKeyExA( + HKEY_CURRENT_USER, appInfoKeyPath.c_str(), 0, nullptr, 0, KEY_WRITE, nullptr, appInfoKey.put(), + nullptr + )); + + { + const std::wstring wAppName = utf8_to_wstring(appName); + winrt::check_win32(RegSetValueExW( + appInfoKey.get(), L"DisplayName", 0, REG_SZ, reinterpret_cast(wAppName.c_str()), + static_cast(wAppName.size() * sizeof(wchar_t)) + )); + } + + if (iconPath.has_value()) { + const auto v = iconPath.value(); + const std::wstring wIcon = utf8_to_wstring(v); + winrt::check_win32(RegSetValueExW( + appInfoKey.get(), L"IconUri", 0, REG_SZ, reinterpret_cast(wIcon.c_str()), + static_cast(wIcon.size() * sizeof(wchar_t)) + )); + } + + // combine guid to class id + ss.clear(); + ss.str(std::string()); + ss << '{' << guid << '}'; + const auto clsid = ss.str(); + + // register the guid of the notification activation callback + winrt::check_win32(RegSetValueExA( + appInfoKey.get(), "CustomActivator", 0, REG_SZ, reinterpret_cast(clsid.c_str()), + static_cast(clsid.size() + 1 * sizeof(char)) + )); +} + +/// Register the notification activation callback factory +/// and the guid of the callback. +bool RegisterCallback(const std::string& guid, NativeNotificationCallback callback) { + DWORD registration {}; + winrt::guid rclsid = parseGuid(guid); + const auto factory_ref = winrt::make_self(); + const auto factory = factory_ref.get(); + factory->callback = callback; + winrt::check_hresult( + CoRegisterClassObject(rclsid, factory, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, ®istration) + ); + return true; +} + +bool NativePlugin::registerApp( + const string& aumid, const string& appName, const string& guid, const optional& iconPath, + NativeNotificationCallback callback +) { + UpdateRegistry(aumid, appName, guid, iconPath); + return RegisterCallback(guid, callback); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/plugin.hpp b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/plugin.hpp new file mode 100755 index 00000000..97d53dbc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/plugin.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include +#include + +#include // <-- This must be the first Windows header +#include + +#include "ffi_api.h" + +using std::optional; +using std::string; +using namespace winrt::Windows::UI::Notifications; + +/// The C++ container object for WinRT handles. +/// +/// Note that this must be a struct as it was forward-declared as a struct in +/// `ffi_api.h`, which cannot use classes as it must be C-compatible. +struct NativePlugin { + /// Whether the plugin has been properly initialized. + bool isReady = false; + + /// Whether the current application has package identity (ie, was packaged with an MSIX). + /// + /// See [hasPackageIdentity]. + bool hasIdentity = false; + + /// The app user model ID. Used instead of package identity when [hasIdentity] is false. + /// + /// For more details, see https://learn.microsoft.com/en-us/windows/win32/shell/appids + winrt::hstring aumid; + + /// The API responsible for showing notifications. Null if [isReady] is false. + optional notifier; + + /// The API responsible for querying shown notifications. Null if [isReady] is false. + optional history; + + /// A callback to run when a notification is pressed, when the app is or is not running. + NativeNotificationCallback callback; + + NativePlugin() {} + ~NativePlugin() {} + + /// Registers the given [callback] to run when a notification is pressed. + bool registerApp( + const string& aumid, const string& appName, const string& guid, + const optional& iconPath, NativeNotificationCallback callback + ); +}; diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/utils.cpp new file mode 100755 index 00000000..b4f9d439 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/utils.cpp @@ -0,0 +1,98 @@ +#include + +#include "utils.hpp" +#include + +char* toNativeString(string str) { + const auto size = (int) str.size() + 1; // + 1 for null terminator + const auto result = new char[size]; + strcpy_s(result, size, str.c_str()); + return result; +} + +NativeStringMap toNativeMap(vector entries) { + const auto size = (int) entries.size(); + const auto array = new StringMapEntry[size]; + std::copy(entries.begin(), entries.end(), array); + return {array, size}; +} + +NotificationData dataFromMap(NativeStringMap map) { + NotificationData data; + for (int index = 0; index < map.size; index++) { + const auto key = winrt::to_hstring(map.entries[index].key); + const auto value = winrt::to_hstring(map.entries[index].value); + data.Values().Insert(key, value); + } + return data; +} + +std::wstring utf8_to_wstring(const std::string& utf8) { + int len = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0); + winrt::check_win32(len != 0 ? ERROR_SUCCESS : GetLastError()); + std::wstring wstr(static_cast(len), L'\0'); + int len2 = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, wstr.data(), len); + winrt::check_win32(len2 != 0 ? ERROR_SUCCESS : GetLastError()); + return wstr; +} + +constexpr uint8_t hex_to_uint(const char c) { + if (c >= '0' && c <= '9') { + return static_cast(c - '0'); + } else if (c >= 'A' && c <= 'F') { + return static_cast(10 + c - 'A'); + } else if (c >= 'a' && c <= 'f') { + return static_cast(10 + c - 'a'); + } else { + throw std::invalid_argument("Character is not a hexadecimal digit"); + } +} + +constexpr uint8_t hex_to_uint8(const char a, const char b) { + return (hex_to_uint(a) << 4) | hex_to_uint(b); +} + +constexpr uint16_t uint8_to_uint16(uint8_t a, uint8_t b) { + return (static_cast(a) << 8) | static_cast(b); +} + +constexpr uint32_t uint8_to_uint32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + return (static_cast(uint8_to_uint16(a, b)) << 16) + | static_cast(uint8_to_uint16(c, d)); +} + +winrt::guid parseGuid(const std::string& guidString) { + // clang-format off + if ( + guidString.size() != 36 + || guidString[8] != '-' + || guidString[13] != '-' + || guidString[18] != '-' + || guidString[23] != '-' + ) { + throw std::invalid_argument("guidString is not a valid GUID string"); + } + // clang-format on + return { + uint8_to_uint32( + hex_to_uint8(guidString[0], guidString[1]), hex_to_uint8(guidString[2], guidString[3]), + hex_to_uint8(guidString[4], guidString[5]), hex_to_uint8(guidString[6], guidString[7]) + ), + uint8_to_uint16( + hex_to_uint8(guidString[9], guidString[10]), hex_to_uint8(guidString[11], guidString[12]) + ), + uint8_to_uint16( + hex_to_uint8(guidString[14], guidString[15]), hex_to_uint8(guidString[16], guidString[17]) + ), + { + hex_to_uint8(guidString[19], guidString[20]), + hex_to_uint8(guidString[21], guidString[22]), + hex_to_uint8(guidString[24], guidString[25]), + hex_to_uint8(guidString[26], guidString[27]), + hex_to_uint8(guidString[28], guidString[29]), + hex_to_uint8(guidString[30], guidString[31]), + hex_to_uint8(guidString[32], guidString[33]), + hex_to_uint8(guidString[34], guidString[35]), + } + }; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/utils.hpp b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/utils.hpp new file mode 100755 index 00000000..ffe9cbbc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/src/utils.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include // <-- This must be the first Windows header +#include +#include +#include + +#include "ffi_api.h" + +using std::string; +using std::vector; +using namespace winrt::Windows::UI::Notifications; + +/// Allocates and returns a char array representing the original C++ string. +char* toNativeString(string str); + +/// Allocates and returns a [NativeStringMap] with the given key-value pairs. +NativeStringMap toNativeMap(vector entries); + +/// Parses a [NativeStringMap] into a WinRT [NotificationData]. +NotificationData dataFromMap(NativeStringMap map); + +std::wstring utf8_to_wstring(const std::string& utf8); +winrt::guid parseGuid(const std::string& guidString); diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/bindings_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/bindings_test.dart new file mode 100755 index 00000000..0f1c921a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/bindings_test.dart @@ -0,0 +1,58 @@ +import 'package:flutter_local_notifications_windows/flutter_local_notifications_windows.dart'; +import 'package:test/test.dart'; + +const WindowsInitializationSettings settings = WindowsInitializationSettings( + appName: 'Test app', + appUserModelId: 'com.test.test', + guid: 'a8c22b55-049e-422f-b30f-863694de08c8', +); + +const Map bindings = { + 'title': 'Bindings title', + 'body': 'Bindings body', +}; + +void main() => group('Bindings', () { + final FlutterLocalNotificationsWindows plugin = + FlutterLocalNotificationsWindows(); + setUpAll(() => plugin.initialize(settings)); + tearDownAll(() async { + await plugin.cancelAll(); + plugin.dispose(); + }); + + test('work in simple cases', () async { + await plugin.show(500, '{title}', '{body}'); + final NotificationUpdateResult result = + await plugin.updateBindings(id: 500, bindings: bindings); + expect(result, NotificationUpdateResult.success); + }); + + test('fail when ID is not found in simple cases', () async { + await plugin.show(501, '{title}', '{body}'); + final NotificationUpdateResult result = + await plugin.updateBindings(id: 599, bindings: bindings); + expect(result, NotificationUpdateResult.notFound); + }); + + test('are included in show()', () async { + await plugin.show( + 502, + '{title}', + '{body}', + details: const WindowsNotificationDetails(bindings: bindings), + ); + }); + + test('fail when notification has been cancelled', () async { + await Future.delayed(const Duration(milliseconds: 200)); + await plugin.show(503, '{title}', '{body}'); + final NotificationUpdateResult result = + await plugin.updateBindings(id: 503, bindings: bindings); + expect(result, NotificationUpdateResult.success); + await plugin.cancelAll(); + final NotificationUpdateResult result2 = + await plugin.updateBindings(id: 503, bindings: bindings); + expect(result2, NotificationUpdateResult.notFound); + }); + }); diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/details_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/details_test.dart new file mode 100755 index 00000000..ea90159c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/details_test.dart @@ -0,0 +1,257 @@ +import 'package:flutter_local_notifications_windows/flutter_local_notifications_windows.dart'; +import 'package:flutter_local_notifications_windows/src/details/notification_to_xml.dart'; +import 'package:test/test.dart'; + +const WindowsInitializationSettings settings = WindowsInitializationSettings( + appName: 'Test app', + appUserModelId: 'com.test.test', + guid: 'a8c22b55-049e-422f-b30f-863694de08c8', +); + +extension PluginUtils on FlutterLocalNotificationsWindows { + static int id = 15; + + void testDetails(WindowsNotificationDetails details) => expect( + isValidXml( + notificationToXml( + title: 'title', + body: 'body', + payload: 'payload', + details: details, + ), + ), + isTrue, + ); +} + +void main() => group('Details:', () { + final FlutterLocalNotificationsWindows plugin = + FlutterLocalNotificationsWindows(); + setUpAll(() => plugin.initialize(settings)); + tearDownAll(() async { + await plugin.cancelAll(); + plugin.dispose(); + }); + + test('No details', () async { + expect(plugin.show(100, null, null), completes); + expect(plugin.show(101, 'Title', null), completes); + expect(plugin.show(102, null, 'Body'), completes); + expect(plugin.show(103, 'Title', 'Body'), completes); + expect(plugin.show(-1, 'Negative ID', 'Body'), completes); + }); + + test( + 'Simple details', + () async => plugin + ..testDetails(const WindowsNotificationDetails()) + ..testDetails( + const WindowsNotificationDetails(subtitle: 'Subtitle')) + ..testDetails(const WindowsNotificationDetails( + duration: WindowsNotificationDuration.long)) + ..testDetails(const WindowsNotificationDetails( + scenario: WindowsNotificationScenario.reminder)) + ..testDetails(WindowsNotificationDetails(timestamp: DateTime.now())) + ..testDetails(const WindowsNotificationDetails( + subtitle: '{message}', + bindings: {'message': 'Hello, Mr. Person'}))); + + test('Actions', () { + const WindowsAction simpleAction = + WindowsAction(content: 'Press me', arguments: '123'); + final WindowsAction complexAction = WindowsAction( + content: 'content', + arguments: 'args', + activationBehavior: WindowsNotificationBehavior.pendingUpdate, + buttonStyle: WindowsButtonStyle.success, + inputId: 'input-id', + tooltip: 'tooltip', + imageUri: WindowsImage.getAssetUri('test/icon.png'), + ); + plugin + ..testDetails(const WindowsNotificationDetails( + actions: [simpleAction])) + ..testDetails(WindowsNotificationDetails( + actions: [complexAction])) + ..testDetails(WindowsNotificationDetails( + actions: List.filled(5, simpleAction))); + expect( + () => notificationToXml( + details: WindowsNotificationDetails( + actions: List.filled(6, simpleAction), + )), + throwsArgumentError, + ); + }); + + test( + 'Audio', + () => plugin + ..testDetails(WindowsNotificationDetails( + audio: WindowsNotificationAudio.silent())) + ..testDetails(WindowsNotificationDetails( + audio: WindowsNotificationAudio.preset( + sound: WindowsNotificationSound.call10)))); + + test('Rows', () { + const WindowsColumn emptyColumn = + WindowsColumn([]); + final WindowsImage image = WindowsImage( + WindowsImage.getAssetUri('test/icon.png'), + altText: 'an icon', + ); + const WindowsNotificationText text = + WindowsNotificationText(text: 'Text'); + final WindowsColumn simpleColumn = + WindowsColumn([image, text]); + final WindowsRow bigRow = WindowsRow( + List.filled(5, simpleColumn), + ); + plugin + ..testDetails(const WindowsNotificationDetails()) + ..testDetails(const WindowsNotificationDetails( + rows: [WindowsRow([])])) + ..testDetails(const WindowsNotificationDetails(rows: [ + WindowsRow([emptyColumn]) + ])) + ..testDetails(WindowsNotificationDetails(rows: [ + WindowsRow([simpleColumn]) + ])) + ..testDetails(WindowsNotificationDetails(rows: [bigRow])) + ..testDetails(WindowsNotificationDetails( + rows: List.filled(5, bigRow))); + }); + + test('Header', () async { + const WindowsHeader header = WindowsHeader( + id: 'header1', + title: 'Header 1', + arguments: 'args1', + activation: WindowsHeaderActivation.foreground, + ); + plugin + ..testDetails(const WindowsNotificationDetails(header: header)) + ..testDetails(const WindowsNotificationDetails(header: header)); + }); + + test('Images', () async { + final WindowsImage simpleImage = WindowsImage( + WindowsImage.getAssetUri('asset.png'), + altText: 'an icon', + ); + final WindowsImage complexImage = WindowsImage( + Uri.parse('https://picsum.photos/500'), + altText: 'an icon', + addQueryParams: true, + crop: WindowsImageCrop.circle, + placement: WindowsImagePlacement.appLogoOverride, + ); + plugin + ..testDetails( + WindowsNotificationDetails(images: [simpleImage])) + ..testDetails(WindowsNotificationDetails( + images: [simpleImage, complexImage])) + ..testDetails( + WindowsNotificationDetails( + images: List.filled(6, simpleImage), + ), + ); + }); + + test('Inputs', () async { + const WindowsTextInput textInput = WindowsTextInput( + id: 'input', + placeHolderContent: 'Text hint', + title: 'Text title', + ); + const WindowsSelectionInput selection = WindowsSelectionInput( + id: 'input', + items: [ + WindowsSelection(id: 'item1', content: 'Item 1'), + WindowsSelection(id: 'item2', content: 'Item 2'), + WindowsSelection(id: 'item3', content: 'Item 3'), + ], + ); + const WindowsAction action = WindowsAction( + content: 'Submit', + arguments: 'submit', + inputId: 'input', + ); + plugin + ..testDetails(const WindowsNotificationDetails( + inputs: [textInput])) + ..testDetails(const WindowsNotificationDetails( + inputs: [selection])) + ..testDetails( + WindowsNotificationDetails( + inputs: List.filled(5, textInput), + ), + ) + ..testDetails(const WindowsNotificationDetails( + inputs: [textInput], + actions: [action])) + ..testDetails(const WindowsNotificationDetails( + inputs: [selection, textInput], + actions: [action])); + expect( + () => notificationToXml( + details: WindowsNotificationDetails( + inputs: List.filled(6, textInput), + ), + ), + throwsArgumentError, + ); + }); + + test('Progress', () async { + final WindowsProgressBar simple = WindowsProgressBar( + id: 'simple', + status: 'Testing...', + value: 0.25, + ); + final WindowsProgressBar complex = WindowsProgressBar( + id: 'complex', + status: 'Testing...', + value: 0.75, + label: 'Progress label', + title: 'Progress title', + ); + final WindowsProgressBar dynamic = WindowsProgressBar( + id: 'dynamic', + status: 'Testing...', + value: 0, + ); + plugin + ..testDetails(WindowsNotificationDetails( + progressBars: [simple])) + ..testDetails(WindowsNotificationDetails( + progressBars: [complex])) + ..testDetails(WindowsNotificationDetails( + progressBars: [simple, complex])) + ..testDetails( + WindowsNotificationDetails( + progressBars: List.filled(6, simple), + ), + ); + await plugin.show( + 201, + null, + null, + details: WindowsNotificationDetails( + progressBars: [dynamic], + ), + ); + for (double i = 0; i <= 1.5; i += 0.05) { + dynamic.value = i; + final NotificationUpdateResult result = await plugin + .updateProgressBar(notificationId: 201, progressBar: dynamic); + expect(result, NotificationUpdateResult.success); + await Future.delayed(const Duration(milliseconds: 10)); + } + expect( + await plugin.updateProgressBar( + notificationId: 202, progressBar: dynamic), + NotificationUpdateResult.notFound, + ); + }); + }); diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/icon.png b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/icon.png new file mode 100755 index 00000000..4d6372ee Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/icon.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/plugin_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/plugin_test.dart new file mode 100755 index 00000000..7564ec32 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/plugin_test.dart @@ -0,0 +1,108 @@ +import 'package:flutter_local_notifications_platform_interface/flutter_local_notifications_platform_interface.dart'; +import 'package:flutter_local_notifications_windows/flutter_local_notifications_windows.dart'; +import 'package:test/test.dart'; +import 'package:timezone/data/latest_all.dart'; +import 'package:timezone/standalone.dart'; + +const WindowsInitializationSettings goodSettings = + WindowsInitializationSettings( + appName: 'test', + appUserModelId: 'com.test.test', + guid: 'a8c22b55-049e-422f-b30f-863694de08c8', +); + +const WindowsInitializationSettings badSettings = WindowsInitializationSettings( + appName: 'test', + appUserModelId: 'com.test.test', + guid: '123', +); + +void main() => group('Plugin', () { + setUpAll(initializeTimeZones); + + test('initializes safely', () async { + final FlutterLocalNotificationsWindows plugin = + FlutterLocalNotificationsWindows(); + final bool result = await plugin.initialize(goodSettings); + expect(result, isTrue); + plugin.dispose(); + }); + + test('catches bad GUIDs', () async { + final FlutterLocalNotificationsWindows plugin = + FlutterLocalNotificationsWindows(); + expect(plugin.initialize(badSettings), throwsArgumentError); + plugin.dispose(); + }); + + test('cannot be used before initializing', () async { + final FlutterLocalNotificationsWindows plugin = + FlutterLocalNotificationsWindows(); + final WindowsProgressBar progress = + WindowsProgressBar(id: 'progress', status: 'Testing', value: 0); + final TZDateTime now = TZDateTime.local(2024, 7, 18); + expect(plugin.cancel(0), throwsStateError); + expect(plugin.cancelAll(), throwsStateError); + expect(plugin.getActiveNotifications(), throwsStateError); + expect(plugin.getNotificationAppLaunchDetails(), throwsStateError); + expect(plugin.pendingNotificationRequests(), throwsStateError); + expect(plugin.show(0, 'Title', 'Body'), throwsStateError); + expect(plugin.showRawXml(id: 0, xml: ''), throwsStateError); + expect( + plugin.updateBindings(id: 0, bindings: {}), + throwsStateError, + ); + expect( + plugin.updateProgressBar(progressBar: progress, notificationId: 0), + throwsStateError, + ); + expect( + plugin.zonedSchedule(0, null, null, now, null), + throwsStateError, + ); + plugin.dispose(); + }); + + test('cannot be used after disposed', () async { + final FlutterLocalNotificationsWindows plugin = + FlutterLocalNotificationsWindows(); + final WindowsProgressBar progress = + WindowsProgressBar(id: 'progress', status: 'Testing', value: 0); + final TZDateTime now = TZDateTime.local(2024, 7, 18); + await plugin.initialize(goodSettings); + plugin.dispose(); + expect(plugin.cancel(0), throwsStateError); + expect(plugin.cancelAll(), throwsStateError); + expect(plugin.getActiveNotifications(), throwsStateError); + expect(plugin.getNotificationAppLaunchDetails(), throwsStateError); + expect(plugin.pendingNotificationRequests(), throwsStateError); + expect(plugin.show(0, 'Title', 'Body'), throwsStateError); + expect(plugin.showRawXml(id: 0, xml: ''), throwsStateError); + expect( + plugin.updateBindings(id: 0, bindings: {}), + throwsStateError, + ); + expect( + plugin.updateProgressBar(progressBar: progress, notificationId: 0), + throwsStateError, + ); + expect( + plugin.zonedSchedule(0, null, null, now, null), throwsStateError); + plugin.dispose(); + }); + + test('does not support repeating notifications', () async { + final FlutterLocalNotificationsWindows plugin = + FlutterLocalNotificationsWindows(); + await plugin.initialize(goodSettings); + expect( + plugin.periodicallyShow(0, null, null, RepeatInterval.everyMinute), + throwsUnsupportedError, + ); + expect( + plugin.periodicallyShowWithDuration(0, null, null, Duration.zero), + throwsUnsupportedError, + ); + plugin.dispose(); + }); + }); diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/scheduled_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/scheduled_test.dart new file mode 100755 index 00000000..08e2cbbf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/scheduled_test.dart @@ -0,0 +1,35 @@ +import 'package:flutter_local_notifications_windows/flutter_local_notifications_windows.dart'; +import 'package:test/test.dart'; +import 'package:timezone/data/latest_all.dart'; +import 'package:timezone/standalone.dart'; + +const WindowsInitializationSettings settings = WindowsInitializationSettings( + appName: 'Test app', + appUserModelId: 'com.test.test', + guid: 'a8c22b55-049e-422f-b30f-863694de08c8'); + +void main() => group('Schedules', () { + final FlutterLocalNotificationsWindows plugin = + FlutterLocalNotificationsWindows(); + setUpAll(initializeTimeZones); + setUpAll(() => plugin.initialize(settings)); + tearDownAll(() async { + await plugin.cancelAll(); + plugin.dispose(); + }); + + Future countPending() async => + (await plugin.pendingNotificationRequests()).length; + late final Location location = getLocation('US/Eastern'); + + test('do not work with earlier time', () async { + final TZDateTime now = TZDateTime.now(location); + final TZDateTime earlier = now.subtract(const Duration(days: 1)); + await plugin.cancelAll(); + expect(await countPending(), 0); + expect(plugin.zonedSchedule(302, null, null, now, null), + throwsArgumentError); + expect(plugin.zonedSchedule(302, null, null, earlier, null), + throwsArgumentError); + }); + }); diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/sound.mp3 b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/sound.mp3 new file mode 100755 index 00000000..60dbf979 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/sound.mp3 differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/xml_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/xml_test.dart new file mode 100755 index 00000000..e2998f19 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/test/xml_test.dart @@ -0,0 +1,81 @@ +import 'package:flutter_local_notifications_windows/flutter_local_notifications_windows.dart'; +import 'package:test/test.dart'; + +const WindowsInitializationSettings settings = WindowsInitializationSettings( + appName: 'test', + appUserModelId: 'com.test.test', + guid: 'a8c22b55-049e-422f-b30f-863694de08c8', +); + +const String emptyXml = ''; +const String invalidXml = 'Blah blah blah'; +const String notWindowsXml = 'Hi'; +const String unmatchedXml = 'Hi'; +const String validXml = ''' + + + + + Hello World + This is a simple toast message + + + + +'''; + +const String complexXml = ''' + + + + + Surface Launch Party + Studio S / Ballroom + 4:00 PM, 10/26/2015 + + + + + + + + + + + + + + + + + + +'''; + +void main() { + group('XML', () { + final FlutterLocalNotificationsWindows plugin = + FlutterLocalNotificationsWindows(); + + setUpAll(() => plugin.initialize(settings)); + tearDownAll(() async { + await plugin.cancelAll(); + plugin.dispose(); + }); + + test('catches invalid XML', () async { + expect(plugin.isValidXml(emptyXml), isFalse); + expect(plugin.isValidXml(invalidXml), isFalse); + expect(plugin.isValidXml(notWindowsXml), isFalse); + expect(plugin.isValidXml(unmatchedXml), isFalse); + expect(plugin.isValidXml(validXml), isTrue); + expect(plugin.isValidXml(complexXml), isTrue); + }); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/windows/CMakeLists.txt new file mode 100755 index 00000000..33c938e4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/flutter_local_notifications_windows/windows/CMakeLists.txt @@ -0,0 +1,24 @@ +# The Flutter tooling requires that developers have a version of Visual Studio +# installed that includes CMake 3.14 or later. You should not increase this +# version, as doing so will cause the plugin to fail to compile for some +# customers of the plugin. +cmake_minimum_required(VERSION 3.14) + +# Project-level configuration. +set(PROJECT_NAME "flutter_local_notifications_windows") +project(${PROJECT_NAME} LANGUAGES CXX) + +# Invoke the build for native code shared with the other target platforms. +# This can be changed to accommodate different builds. +add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared") + +# List of absolute paths to libraries that should be bundled with the plugin. +# This list could contain prebuilt libraries, or libraries created by an +# external build triggered from this build file. +set(flutter_local_notifications_windows_bundled_libraries + # Defined in ../src/CMakeLists.txt. + # This can be changed to accommodate different builds. + $ + PARENT_SCOPE +) +target_link_libraries(flutter_local_notifications_windows PRIVATE runtimeobject) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows deleted file mode 120000 index 6a33d5af..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/geolocator_windows-0.2.5/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/AUTHORS b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/AUTHORS new file mode 100755 index 00000000..699cdd42 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/AUTHORS @@ -0,0 +1,7 @@ + +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Alexandre Zollinger Chohfi \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/CHANGELOG.md new file mode 100755 index 00000000..ba88e95a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/CHANGELOG.md @@ -0,0 +1,44 @@ +## 0.2.5 + +- Bump `flutter_lints` to version 5.0.0 + +## 0.2.4 + +* Updates dart SDk to `sdk: ^3.5.0` +* Fixed analyzzer issues example project + +## 0.2.3 + +* Fixes crash under Windows when RequestAcess is called while the Geolocation Service is disabled. (#1455) + +## 0.2.2 + +* Fixes crash under Windows when getCurrentPosition method is called. (#1240) + +## 0.2.1 + +* Exposes altitude accuracy to the `Position` class. + +## 0.2.0 + +* **BREAKING CHANGE:** Synchronizes the default values of `Position.altitude`, `Position.heading` and `Position.speed` with the other platforms and return 0.0 if the value is not known. +* Migrates the `target_compile_options` to use `/await:strict` to make the options compatible with C++ 20. + +## 0.1.3 + +* Adds a `PositionStatus::Initializing` status consideration since it triggers the state change +if "Let apps access your location" toggle option is switched ON from OFF. + +## 0.1.2 + +* Adds improved Flutter analysis and resolved warnings. +* Updates dependencies to current versions. +* Fixes plugin registration in `dart_plugin_registrant.dart`. + +## 0.1.1 + +* Fixes repository URL of the package. + +## 0.1.0 + +* Adds an initial implementation of Windows support for the geolocator plugin. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/LICENSE new file mode 100755 index 00000000..f150c852 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Baseflow + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/README.md new file mode 100755 index 00000000..ca97e42e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/README.md @@ -0,0 +1,23 @@ +# geolocator_windows + +[![pub package](https://img.shields.io/pub/v/geolocator.svg)](https://pub.dartlang.org/packages/geolocator) ![Build status](https://github.com/Baseflow/flutter-geolocator/workflows/geolocator_windows/badge.svg?branch=master) [![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://github.com/tenhobi/effective_dart) + +The official Windows implementation of the [geolocator](https://pub.dev/packages/geolocator) plugin by [Baseflow](https://baseflow.com). + +## Usage + +Since version 8.1.0 of the [geolocator](https://pub.dev/packages/geolocator) plugin this is the endorsed Windows implementation. This means it will automatically be added to your dependencies when you depend on `geolocator: ^8.1.0` in your applications pubspec.yaml. + +More detailed instructions on using the API can be found in the [README.md](../geolocator/README.md) of the [geolocator](https://pub.dev/packages/geolocator) package. + +## Issues + +Please file any issues, bugs or feature requests as an issue on our [GitHub](https://github.com/Baseflow/flutter-geolocator/issues) page. Commercial support is available, you can contact us at . + +## Want to contribute + +If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-geolocator/pulls). + +## Author + +This Geolocator plugin for Flutter is developed by [Baseflow](https://baseflow.com). \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/analysis_options.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/analysis_options.yaml new file mode 100755 index 00000000..04a0dd67 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/analysis_options.yaml @@ -0,0 +1,10 @@ +include: package:flutter_lints/flutter.yaml + +analyzer: + exclude: + # Ignore generated files + - '**/*.g.dart' + - 'lib/src/generated/*.dart' +linter: + rules: + - public_member_api_docs \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/README.md new file mode 100755 index 00000000..7961082e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/README.md @@ -0,0 +1,16 @@ +# geolocator_windows_example + +Demonstrates how to use the geolocator_windows plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/lib/main.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/lib/main.dart new file mode 100755 index 00000000..d5520fc8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/lib/main.dart @@ -0,0 +1,404 @@ +import 'dart:async'; + +import 'package:baseflow_plugin_template/baseflow_plugin_template.dart'; +import 'package:flutter/material.dart'; +import 'package:geolocator_platform_interface/geolocator_platform_interface.dart'; + +/// Defines the main theme color. +final MaterialColor themeMaterialColor = + BaseflowPluginExample.createMaterialColor( + const Color.fromRGBO(48, 49, 60, 1)); + +void main() { + runApp(const GeolocatorWidget()); +} + +/// Example [Widget] showing the functionalities of the geolocator plugin +class GeolocatorWidget extends StatefulWidget { + /// Creates a new GeolocatorWidget. + const GeolocatorWidget({super.key}); + + /// Utility method to create a page with the Baseflow templating. + static ExamplePage createPage() { + return ExamplePage( + Icons.location_on, (context) => const GeolocatorWidget()); + } + + @override + State createState() => _GeolocatorWidgetState(); +} + +class _GeolocatorWidgetState extends State { + static const String _kLocationServicesDisabledMessage = + 'Location services are disabled.'; + static const String _kPermissionDeniedMessage = 'Permission denied.'; + static const String _kPermissionDeniedForeverMessage = + 'Permission denied forever.'; + static const String _kPermissionGrantedMessage = 'Permission granted.'; + + final GeolocatorPlatform geolocatorWindows = GeolocatorPlatform.instance; + final List<_PositionItem> _positionItems = <_PositionItem>[]; + StreamSubscription? _positionStreamSubscription; + StreamSubscription? _serviceStatusStreamSubscription; + + @override + void initState() { + super.initState(); + _toggleServiceStatusStream(); + } + + PopupMenuButton _createActions() { + return PopupMenuButton( + elevation: 40, + onSelected: (value) async { + switch (value) { + case 1: + _getLocationAccuracy(); + break; + case 2: + _openAppSettings(); + break; + case 3: + _openLocationSettings(); + break; + case 4: + setState(_positionItems.clear); + break; + default: + break; + } + }, + itemBuilder: (context) => [ + const PopupMenuItem( + value: 1, + child: Text('Get Location Accuracy'), + ), + const PopupMenuItem( + value: 2, + child: Text('Open App Settings'), + ), + const PopupMenuItem( + value: 3, + child: Text('Open Location Settings'), + ), + const PopupMenuItem( + value: 4, + child: Text('Clear'), + ) + ]); + } + + @override + Widget build(BuildContext context) { + const sizedBox = SizedBox( + height: 10, + ); + + return BaseflowPluginExample( + pluginName: 'Geolocator', + githubURL: 'https://github.com/Baseflow/flutter-geolocator', + pubDevURL: 'https://pub.dev/packages/geolocator', + appBarActions: [ + _createActions() + ], + pages: [ + ExamplePage( + Icons.location_on, + (context) => Scaffold( + backgroundColor: Theme.of(context).colorScheme.surface, + body: ListView.builder( + itemCount: _positionItems.length, + itemBuilder: (context, index) { + final positionItem = _positionItems[index]; + + if (positionItem.type == _PositionItemType.log) { + return ListTile( + title: Text(positionItem.displayValue, + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + )), + ); + } else { + return Card( + child: ListTile( + tileColor: themeMaterialColor, + title: Text( + positionItem.displayValue, + style: const TextStyle(color: Colors.white), + ), + ), + ); + } + }, + ), + floatingActionButton: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + FloatingActionButton( + onPressed: _toggleListening, + tooltip: (_positionStreamSubscription == null) + ? 'Start position updates' + : _positionStreamSubscription!.isPaused + ? 'Resume' + : 'Pause', + backgroundColor: _determineButtonColor(), + child: (_positionStreamSubscription == null || + _positionStreamSubscription!.isPaused) + ? const Icon(Icons.play_arrow) + : const Icon(Icons.pause), + ), + sizedBox, + FloatingActionButton( + onPressed: _getCurrentPosition, + child: const Icon(Icons.my_location), + ), + sizedBox, + FloatingActionButton( + onPressed: _getLastKnownPosition, + child: const Icon(Icons.bookmark), + ), + ], + ), + ), + ) + ]); + } + + Future _getCurrentPosition() async { + final hasPermission = await _handlePermission(); + + if (!hasPermission) { + return; + } + + final position = await geolocatorWindows.getCurrentPosition(); + _updatePositionList( + _PositionItemType.position, + '$position (Heading: ${position.heading}, Speed: ${position.speed})', + ); + } + + Future _handlePermission() async { + bool serviceEnabled; + LocationPermission permission; + + // Test if location services are enabled. + serviceEnabled = await geolocatorWindows.isLocationServiceEnabled(); + if (!serviceEnabled) { + // Location services are not enabled don't continue + // accessing the position and request users of the + // App to enable the location services. + _updatePositionList( + _PositionItemType.log, + _kLocationServicesDisabledMessage, + ); + + return false; + } + + permission = await geolocatorWindows.checkPermission(); + if (permission == LocationPermission.denied) { + permission = await geolocatorWindows.requestPermission(); + if (permission == LocationPermission.denied) { + // Permissions are denied, next time you could try + // requesting permissions again (this is also where + // Android's shouldShowRequestPermissionRationale + // returned true. According to Android guidelines + // your App should show an explanatory UI now. + _updatePositionList( + _PositionItemType.log, + _kPermissionDeniedMessage, + ); + + return false; + } + } + + if (permission == LocationPermission.deniedForever) { + // Permissions are denied forever, handle appropriately. + _updatePositionList( + _PositionItemType.log, + _kPermissionDeniedForeverMessage, + ); + + return false; + } + + // When we reach here, permissions are granted and we can + // continue accessing the position of the device. + _updatePositionList( + _PositionItemType.log, + _kPermissionGrantedMessage, + ); + return true; + } + + void _updatePositionList(_PositionItemType type, String displayValue) { + _positionItems.add(_PositionItem(type, displayValue)); + setState(() {}); + } + + bool _isListening() => !(_positionStreamSubscription == null || + _positionStreamSubscription!.isPaused); + + Color _determineButtonColor() { + return _isListening() ? Colors.green : Colors.red; + } + + void _toggleServiceStatusStream() { + if (_serviceStatusStreamSubscription == null) { + final serviceStatusStream = geolocatorWindows.getServiceStatusStream(); + _serviceStatusStreamSubscription = + serviceStatusStream.handleError((error) { + _serviceStatusStreamSubscription?.cancel(); + _serviceStatusStreamSubscription = null; + }).listen((serviceStatus) { + String serviceStatusValue; + if (serviceStatus == ServiceStatus.enabled) { + serviceStatusValue = 'enabled'; + } else { + serviceStatusValue = 'disabled'; + } + _updatePositionList( + _PositionItemType.log, + 'Location service has been $serviceStatusValue', + ); + }); + } + } + + void _toggleListening() { + Exception? error; + + if (_positionStreamSubscription == null) { + final Stream positionStream = + geolocatorWindows.getPositionStream(); + _positionStreamSubscription = positionStream.handleError((e) { + _positionStreamSubscription?.cancel(); + _positionStreamSubscription = null; + error = e; + }).listen((position) => _updatePositionList( + _PositionItemType.position, + position.toString(), + )); + _positionStreamSubscription?.pause(); + } + + setState(() { + if (_positionStreamSubscription == null) { + return; + } + + if (error != null) { + _updatePositionList(_PositionItemType.log, error.toString()); + return; + } + + String statusDisplayValue; + if (_positionStreamSubscription!.isPaused) { + _positionStreamSubscription!.resume(); + statusDisplayValue = 'resumed'; + } else { + _positionStreamSubscription!.pause(); + statusDisplayValue = 'paused'; + } + + _updatePositionList( + _PositionItemType.log, + 'Listening for position updates $statusDisplayValue', + ); + }); + } + + @override + void dispose() { + if (_positionStreamSubscription != null) { + _positionStreamSubscription!.cancel(); + _positionStreamSubscription = null; + } + + super.dispose(); + } + + void _getLastKnownPosition() async { + final position = await geolocatorWindows.getLastKnownPosition(); + if (position != null) { + _updatePositionList( + _PositionItemType.position, + position.toString(), + ); + } else { + _updatePositionList( + _PositionItemType.log, + 'No last known position available', + ); + } + } + + void _getLocationAccuracy() async { + final status = await geolocatorWindows.getLocationAccuracy(); + _handleLocationAccuracyStatus(status); + } + + void _handleLocationAccuracyStatus(LocationAccuracyStatus status) { + String locationAccuracyStatusValue; + if (status == LocationAccuracyStatus.precise) { + locationAccuracyStatusValue = 'Precise'; + } else if (status == LocationAccuracyStatus.reduced) { + locationAccuracyStatusValue = 'Reduced'; + } else { + locationAccuracyStatusValue = 'Unknown'; + } + _updatePositionList( + _PositionItemType.log, + '$locationAccuracyStatusValue location accuracy granted.', + ); + } + + void _openAppSettings() async { + final opened = await geolocatorWindows.openAppSettings(); + String displayValue; + + if (opened) { + displayValue = 'Opened Application Settings.'; + } else { + displayValue = 'Error opening Application Settings.'; + } + + _updatePositionList( + _PositionItemType.log, + displayValue, + ); + } + + void _openLocationSettings() async { + final opened = await geolocatorWindows.openLocationSettings(); + String displayValue; + + if (opened) { + displayValue = 'Opened Location Settings'; + } else { + displayValue = 'Error opening Location Settings'; + } + + _updatePositionList( + _PositionItemType.log, + displayValue, + ); + } +} + +enum _PositionItemType { + log, + position, +} + +class _PositionItem { + _PositionItem(this.type, this.displayValue); + + final _PositionItemType type; + final String displayValue; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/pubspec.yaml new file mode 100755 index 00000000..37856a74 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/pubspec.yaml @@ -0,0 +1,43 @@ +name: geolocator_windows_example +description: Demonstrates how to use the geolocator_windows plugin. + +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +environment: + sdk: ^3.5.0 + +dependencies: + baseflow_plugin_template: ^2.1.2 + flutter: + sdk: flutter + + geolocator_platform_interface: ^4.0.7 + geolocator_windows: + # When depending on this package from a real application you should use: + # geolocator_windows: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.1+1 + + # The following adds the URL Launcher plugin which is used by + # the demo application to open the links in the web browser. + url_launcher: ^6.0.18 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + uses-material-design: true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/baseflow_logo_def_light-02.png b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/baseflow_logo_def_light-02.png new file mode 100755 index 00000000..85f071f2 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/baseflow_logo_def_light-02.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight.png b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight.png new file mode 100755 index 00000000..6b9f1aae Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight@2x.png new file mode 100755 index 00000000..66901d9e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight@3x.png new file mode 100755 index 00000000..36fbdff3 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight_2020-06-23.zip b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight_2020-06-23.zip new file mode 100755 index 00000000..9c945d08 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/res/images/poweredByBaseflowLogoLight_2020-06-23.zip differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/CMakeLists.txt new file mode 100755 index 00000000..1633297a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.14) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..b2e4bd8d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/generated_plugin_registrant.cc b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/generated_plugin_registrant.cc new file mode 100755 index 00000000..94586cc4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,17 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + GeolocatorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("GeolocatorWindows")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/generated_plugin_registrant.h b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/generated_plugin_registrant.h new file mode 100755 index 00000000..dc139d85 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/generated_plugins.cmake b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/generated_plugins.cmake new file mode 100755 index 00000000..f0bcafdb --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,25 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + geolocator_windows + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..de2d8916 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/Runner.rc b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/Runner.rc new file mode 100755 index 00000000..0f5c0857 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/flutter_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..b43b9095 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/flutter_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..6da0652f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/main.cpp new file mode 100755 index 00000000..bcb57b0e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/resource.h b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/resource.h new file mode 100755 index 00000000..66a65d1e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/resources/app_icon.ico b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/resources/app_icon.ico differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/runner.exe.manifest b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/utils.cpp new file mode 100755 index 00000000..d19bdbbc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/utils.h new file mode 100755 index 00000000..3879d547 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/win32_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..c10f08dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/win32_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/win32_window.h new file mode 100755 index 00000000..17ba4311 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/example/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/pubspec.yaml new file mode 100755 index 00000000..0b58b73e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/pubspec.yaml @@ -0,0 +1,28 @@ +name: geolocator_windows +description: Geolocation Windows plugin for Flutter. This plugin provides the Windows implementation for the geolocator. +repository: https://github.com/baseflow/flutter-geolocators +issue_tracker: https://github.com/baseflow/flutter-geolocator/issues?q=is%3Aissue+is%3Aopen +version: 0.2.5 + +environment: + sdk: ^3.5.0 + flutter: ">=2.8.0" + +flutter: + plugin: + implements: geolocator + platforms: + windows: + pluginClass: GeolocatorWindows + +dependencies: + flutter: + sdk: flutter + geolocator_platform_interface: ^4.1.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ">=3.0.1 <5.0.0" + mockito: ^5.0.17 + plugin_platform_interface: ^2.1.2 diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/CMakeLists.txt new file mode 100755 index 00000000..23323dca --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/CMakeLists.txt @@ -0,0 +1,107 @@ +cmake_minimum_required(VERSION 3.15) +set(PROJECT_NAME "geolocator_windows") +cmake_policy(VERSION 3.15...3.24) +set(CPPWINRT_VERSION "2.0.220418.1") +project(${PROJECT_NAME} LANGUAGES CXX) +include(FetchContent) + +set(PLUGIN_NAME "${PROJECT_NAME}_plugin") + +list(APPEND PLUGIN_SOURCES + "geolocator_plugin.cpp" + "geolocator_plugin.h" + "geolocator_enums.h" +) + +FetchContent_Declare(nuget + URL "https://dist.nuget.org/win-x86-commandline/v6.0.0/nuget.exe" + URL_HASH SHA256=04eb6c4fe4213907e2773e1be1bbbd730e9a655a3c9c58387ce8d4a714a5b9e1 + DOWNLOAD_NO_EXTRACT true +) + +find_program(NUGET nuget) +if (NOT NUGET) + message("Nuget.exe not found, trying to download or use cached version.") + FetchContent_MakeAvailable(nuget) + set(NUGET ${nuget_SOURCE_DIR}/nuget.exe) +endif() + +execute_process(COMMAND + ${NUGET} install Microsoft.Windows.CppWinRT -Version ${CPPWINRT_VERSION} -OutputDirectory packages + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE ret) +if (NOT ret EQUAL 0) + message(FATAL_ERROR "Failed to install nuget package Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}") +endif() + +set(CPPWINRT ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}/bin/cppwinrt.exe) +execute_process(COMMAND + ${CPPWINRT} -input sdk -output include + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE ret) +if (NOT ret EQUAL 0) + message(FATAL_ERROR "Failed to run cppwinrt.exe") +endif() + +include_directories(BEFORE SYSTEM ${CMAKE_BINARY_DIR}/include) + +add_library(${PLUGIN_NAME} SHARED + "include/geolocator_windows/geolocator_windows.h" + "geolocator_windows.cpp" + ${PLUGIN_SOURCES} +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) +target_compile_features(${PLUGIN_NAME} PRIVATE cxx_std_20) +target_compile_options(${PLUGIN_NAME} PRIVATE /await:strict) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) + +# List of absolute paths to libraries that should be bundled with the plugin +set(file_chooser_bundled_libraries + "" + PARENT_SCOPE +) + + +# === Tests === + +if (${include_${PROJECT_NAME}_tests}) +set(TEST_RUNNER "${PROJECT_NAME}_test") +enable_testing() +# TODO(stuartmorgan): Consider using a single shared, pre-checked-in googletest +# instance rather than downloading for each plugin. This approach makes sense +# for a template, but not for a monorepo with many plugins. +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/release-1.11.0.zip +) +# Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Disable install commands for gtest so it doesn't end up in the bundle. +set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE) + +FetchContent_MakeAvailable(googletest) + +# The plugin's C API is not very useful for unit testing, so build the sources +# directly into the test binary rather than using the DLL. +add_executable(${TEST_RUNNER} + test/geolocator_windows_test.cpp + ${PLUGIN_SOURCES} +) +apply_standard_settings(${TEST_RUNNER}) +target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") +target_link_libraries(${TEST_RUNNER} PRIVATE flutter_wrapper_plugin) +target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) +# flutter_wrapper_plugin has link dependencies on the Flutter DLL. +add_custom_command(TARGET ${TEST_RUNNER} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${FLUTTER_LIBRARY}" $ +) + +include(GoogleTest) +gtest_discover_tests(${TEST_RUNNER}) +endif() diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_enums.h b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_enums.h new file mode 100755 index 00000000..dfb9e146 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_enums.h @@ -0,0 +1,36 @@ +namespace geolocator_plugin { + +enum ErrorCode { + PermissionDefinitionsNotFound, + OperationCanceled, + UnknownError +}; + +enum LocationPermission { + Denied, + DeniedForever, + WhileInUse, + Always, + UnableToDetermine +}; + +enum LocationAccuracyStatus { + Reduced, + Precise +}; + +enum LocationAccuracy { + Lowest, + Low, + Medium, + High, + Best, + BestForNavigation +}; + +enum ServiceStatus { + Disabled, + Enabled +}; + +} // namespace geolocator_plugin diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_plugin.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_plugin.cpp new file mode 100755 index 00000000..9db2d178 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_plugin.cpp @@ -0,0 +1,314 @@ +#include "geolocator_plugin.h" + +namespace geolocator_plugin { + +using namespace flutter; +using namespace winrt; +using namespace winrt::Windows::Devices::Geolocation; + +namespace { + +template +T GetArgument(const std::string arg, const EncodableValue* args, T fallback) { + T result {fallback}; + const auto* arguments = std::get_if(args); + if (arguments) { + auto result_it = arguments->find(EncodableValue(arg)); + if (result_it != arguments->end()) { + result = std::get(result_it->second); + } + } + return result; +} + +std::string ErrorCodeToString(ErrorCode errorCode) { + switch (errorCode) { + case ErrorCode::PermissionDefinitionsNotFound: + return "PERMISSION_DEFINITIONS_NOT_FOUND"; + case ErrorCode::OperationCanceled: + return "OPERATION_CANCELED"; + case ErrorCode::UnknownError: + return "UNKNOWN_ERROR"; + default: + throw std::logic_error("unexcepted value" + static_cast(errorCode)); + } +} + +} // namespace + +// static +void GeolocatorPlugin::RegisterWithRegistrar( + PluginRegistrar* registrar) { + + auto channel = std::make_unique>( + registrar->messenger(), "flutter.baseflow.com/geolocator", + &StandardMethodCodec::GetInstance()); + + auto geolocatorStreamChannel = std::make_unique>( + registrar->messenger(), "flutter.baseflow.com/geolocator_updates", + &StandardMethodCodec::GetInstance()); + + auto geolocatorServiceStreamChannel = std::make_unique>( + registrar->messenger(), "flutter.baseflow.com/geolocator_service_updates", + &StandardMethodCodec::GetInstance()); + + std::unique_ptr plugin = std::make_unique(); + + auto geolocatorHandler = std::make_unique< + StreamHandlerFunctions>( + [plugin_pointer = plugin.get()]( + const EncodableValue* arguments, + std::unique_ptr>&& events) + -> std::unique_ptr> { + return plugin_pointer->OnListen(arguments, std::move(events)); + }, + [plugin_pointer = plugin.get()](const EncodableValue* arguments) + -> std::unique_ptr> { + return plugin_pointer->OnCancel(arguments); + }); + + geolocatorStreamChannel->SetStreamHandler(std::move(geolocatorHandler)); + + auto geolocatorServiceHandler = std::make_unique< + StreamHandlerFunctions>( + [plugin_pointer = plugin.get()]( + const EncodableValue* arguments, + std::unique_ptr>&& events) + -> std::unique_ptr> { + return plugin_pointer->OnServiceListen(arguments, std::move(events)); + }, + [plugin_pointer = plugin.get()](const EncodableValue* arguments) + -> std::unique_ptr> { + return plugin_pointer->OnServiceCancel(arguments); + }); + + geolocatorServiceStreamChannel->SetStreamHandler(std::move(geolocatorServiceHandler)); + + channel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto& call, auto result) { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); + + registrar->AddPlugin(std::move(plugin)); +} + +GeolocatorPlugin::GeolocatorPlugin(){} + +GeolocatorPlugin::~GeolocatorPlugin() = default; + +void GeolocatorPlugin::HandleMethodCall( + const MethodCall<>& method_call, + std::unique_ptr> result) { + + auto methodName = method_call.method_name(); + if (methodName.compare("checkPermission") == 0) { + OnCheckPermission(std::move(result)); + } else if (methodName.compare("isLocationServiceEnabled") == 0) { + OnIsLocationServiceEnabled(std::move(result)); + } else if (methodName.compare("requestPermission") == 0) { + OnRequestPermission(std::move(result)); + } else if (methodName.compare("getLastKnownPosition") == 0) { + OnGetLastKnownPosition(method_call, std::move(result)); + } else if (methodName.compare("getLocationAccuracy") == 0) { + GetLocationAccuracy(std::move(result)); + } else if (methodName.compare("getCurrentPosition") == 0) { + OnGetCurrentPosition(method_call, std::move(result)); + } else if (methodName.compare("openAppSettings") == 0 + || methodName.compare("openLocationSettings") == 0) { + OpenPrivacyLocationSettings(std::move(result)); + } else { + result->NotImplemented(); + } +} + +void GeolocatorPlugin::OpenPrivacyLocationSettings(std::unique_ptr> result) { + std::wstring url {L"ms-settings:privacy-location"}; + + int status = static_cast(reinterpret_cast( + ::ShellExecuteW(nullptr, TEXT("open"), url.c_str(), + nullptr, nullptr, SW_SHOWNORMAL))); + + // Per ::ShellExecuteW documentation, anything >32 indicates success. + result->Success(status > 32); +} + +winrt::fire_and_forget GeolocatorPlugin::RequestAccessAsync(std::unique_ptr> result) { + try { + auto access = co_await geolocator.RequestAccessAsync(); + if(access == GeolocationAccessStatus::Allowed) + result->Success(EncodableValue((int)LocationPermission::WhileInUse)); + else if(access == GeolocationAccessStatus::Denied) + result->Success(EncodableValue((int)LocationPermission::Denied)); + else if(access == GeolocationAccessStatus::Unspecified) + result->Success(EncodableValue((int)LocationPermission::DeniedForever)); + } + catch(const std::exception& ex) { + result->Error(ErrorCodeToString(ErrorCode::PermissionDefinitionsNotFound), ex.what()); + } + catch (...) { + result->Error(ErrorCodeToString(ErrorCode::UnknownError), "RequestAccess failed. Check the Geolocation Service is running."); + } +} + +void GeolocatorPlugin::OnCheckPermission(std::unique_ptr> result) { + RequestAccessAsync(std::move(result)); +} + +bool isLocationStatusValid (const PositionStatus& status) { + return status != PositionStatus::Disabled + && status != PositionStatus::NotAvailable; +} + +void GeolocatorPlugin::OnIsLocationServiceEnabled(std::unique_ptr> result) { + result->Success(EncodableValue(isLocationStatusValid(geolocator.LocationStatus()))); +} + +void GeolocatorPlugin::OnRequestPermission(std::unique_ptr> result) { + RequestAccessAsync(std::move(result)); +} + +winrt::fire_and_forget GeolocatorPlugin::OnGetLastKnownPosition(const MethodCall<>& method_call, + std::unique_ptr> result) { + try { + auto location = co_await geolocator.GetGeopositionAsync(std::chrono::hours(1), std::chrono::milliseconds::zero()); + result->Success(LocationToEncodableMap(location)); + } + catch (hresult_canceled const& error) { + result->Error(ErrorCodeToString(ErrorCode::OperationCanceled), + to_string(error.message())); + } + catch (hresult_error const& error) { + result->Error(ErrorCodeToString(ErrorCode::UnknownError), + to_string(error.message())); + } +} + +void GeolocatorPlugin::GetLocationAccuracy(std::unique_ptr> result) { + result->Success(EncodableValue((int)( + geolocator.DesiredAccuracy() == PositionAccuracy::High + ? LocationAccuracyStatus::Precise + : LocationAccuracyStatus::Reduced))); +} + +winrt::fire_and_forget GeolocatorPlugin::OnGetCurrentPosition(const MethodCall<>& method_call, + std::unique_ptr> result) { + try { + auto location = co_await geolocator.GetGeopositionAsync(); + result->Success(LocationToEncodableMap(location)); + } + catch (hresult_canceled const& error) { + result->Error(ErrorCodeToString(ErrorCode::OperationCanceled), + to_string(error.message())); + } + catch (hresult_error const& error) { + result->Error(ErrorCodeToString(ErrorCode::UnknownError), + to_string(error.message())); + } +} + +std::unique_ptr> GeolocatorPlugin::OnListen( + const EncodableValue* arguments, + std::unique_ptr>&& events){ + + auto accuracy = LocationAccuracy::Best; + long distanceFilter = 0; + long timeInterval = 1; + + if (arguments != nullptr) { + accuracy = (LocationAccuracy)GetArgument("accuracy", arguments, accuracy); + distanceFilter = GetArgument("distanceFilter", arguments, distanceFilter); + timeInterval = GetArgument("timeInterval", arguments, timeInterval); + } + + m_positionChangedRevoker.revoke(); + + geolocator.DesiredAccuracy(accuracy < LocationAccuracy::Medium + ? PositionAccuracy::Default + : PositionAccuracy::High); + geolocator.MovementThreshold(distanceFilter); + geolocator.ReportInterval(timeInterval); + + m_positionChangedRevoker = geolocator.PositionChanged(winrt::auto_revoke, + [events = std::move(events)](Geolocator const& geolocator, PositionChangedEventArgs e) + { + events->Success(LocationToEncodableMap(e.Position())); + }); + + return nullptr; +} + +std::unique_ptr> GeolocatorPlugin::OnCancel(const EncodableValue* arguments){ + m_positionChangedRevoker.revoke(); + return nullptr; +} + +std::unique_ptr> GeolocatorPlugin::OnServiceListen( + const EncodableValue* arguments, + std::unique_ptr>&& events){ + + m_currentStatus = statusGeolocator.LocationStatus(); + if (m_currentStatus != PositionStatus::Disabled) { + m_currentStatus = PositionStatus::Ready; + } + + m_statusChangedRevoker = statusGeolocator.StatusChanged(winrt::auto_revoke, + [events = std::move(events), this](Geolocator const& geolocator, StatusChangedEventArgs e) + { + if (m_currentStatus != PositionStatus::Disabled && e.Status() == PositionStatus::Disabled + || m_currentStatus != PositionStatus::Ready && e.Status() == PositionStatus::Ready + || m_currentStatus != PositionStatus::Initializing && e.Status() == PositionStatus::Initializing ) { + auto status = e.Status() == PositionStatus::NotAvailable + ? ServiceStatus::Disabled + : ServiceStatus::Enabled; + events->Success(EncodableValue((int)status)); + m_currentStatus = e.Status(); + } + }); + + return nullptr; +} + +std::unique_ptr> GeolocatorPlugin::OnServiceCancel(const EncodableValue* arguments){ + m_statusChangedRevoker.revoke(); + return nullptr; +} + +EncodableMap GeolocatorPlugin::LocationToEncodableMap(Geoposition const& location) { + if (location == nullptr) { + return EncodableMap(); + } + + auto position = EncodableMap(); + + position.insert(std::make_pair(EncodableValue("latitude"), EncodableValue(location.Coordinate().Latitude()))); + position.insert(std::make_pair(EncodableValue("longitude"), EncodableValue(location.Coordinate().Longitude()))); + position.insert(std::make_pair(EncodableValue("timestamp"), EncodableValue(clock::to_time_t(location.Coordinate().Timestamp())))); + + double altitude = location.Coordinate().Altitude() != nullptr && !std::isnan(location.Coordinate().Altitude().GetDouble()) + ? location.Coordinate().Altitude().GetDouble() + : 0; + position.insert(std::make_pair(EncodableValue("altitude"), EncodableValue(altitude))); + + double altitudeAccuracy = location.Coordinate().AltitudeAccuracy() != nullptr && !std::isnan(location.Coordinate().AltitudeAccuracy().GetDouble()) + ? location.Coordinate().AltitudeAccuracy().GetDouble() + : 0; + position.insert(std::make_pair(EncodableValue("altitude_accuracy"), EncodableValue(altitudeAccuracy))); + + position.insert(std::make_pair(EncodableValue("accuracy"), EncodableValue(location.Coordinate().Accuracy()))); + + double heading = location.Coordinate().Heading() != nullptr && !std::isnan(location.Coordinate().Heading().GetDouble()) + ? location.Coordinate().Heading().GetDouble() + : 0; + position.insert(std::make_pair(EncodableValue("heading"), EncodableValue(heading))); + + double speed = location.Coordinate().Speed() != nullptr && !std::isnan(location.Coordinate().Speed().GetDouble()) + ? location.Coordinate().Speed().GetDouble() + : 0; + position.insert(std::make_pair(EncodableValue("speed"), EncodableValue(speed))); + + position.insert(std::make_pair(EncodableValue("is_mocked"), EncodableValue(false))); + + return position; +} + +} // namespace geolocator_plugin diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_plugin.h b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_plugin.h new file mode 100755 index 00000000..5da6b6e3 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_plugin.h @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "geolocator_enums.h" + +namespace geolocator_plugin { + +class GeolocatorPlugin : public flutter::Plugin { + public: + static void RegisterWithRegistrar(flutter::PluginRegistrar* registrar); + + GeolocatorPlugin(); + + virtual ~GeolocatorPlugin(); + + // Disallow copy and move. + GeolocatorPlugin(const GeolocatorPlugin&) = delete; + GeolocatorPlugin& operator=(const GeolocatorPlugin&) = delete; + + // Called when a method is called on the plugin channel. + void HandleMethodCall(const flutter::MethodCall<>&, + std::unique_ptr>); + + private: + void OnCheckPermission(std::unique_ptr>); + void OnIsLocationServiceEnabled(std::unique_ptr>); + void OnRequestPermission(std::unique_ptr>); + winrt::fire_and_forget OnGetLastKnownPosition(const flutter::MethodCall<>&, + std::unique_ptr>); + void GetLocationAccuracy(std::unique_ptr>); + winrt::fire_and_forget OnGetCurrentPosition(const flutter::MethodCall<>&, + std::unique_ptr>); + + winrt::fire_and_forget RequestAccessAsync(std::unique_ptr>); + void OpenPrivacyLocationSettings(std::unique_ptr>); + + winrt::Windows::Devices::Geolocation::Geolocator::PositionChanged_revoker m_positionChangedRevoker; + + std::unique_ptr> OnListen( + const flutter::EncodableValue* arguments, + std::unique_ptr>&& events); + std::unique_ptr> OnCancel( + const flutter::EncodableValue* arguments); + + winrt::Windows::Devices::Geolocation::Geolocator::StatusChanged_revoker m_statusChangedRevoker; + + std::unique_ptr> OnServiceListen( + const flutter::EncodableValue* arguments, + std::unique_ptr>&& events); + std::unique_ptr> OnServiceCancel( + const flutter::EncodableValue* arguments); + + static flutter::EncodableMap LocationToEncodableMap(winrt::Windows::Devices::Geolocation::Geoposition const&); + + winrt::Windows::Devices::Geolocation::Geolocator geolocator; + winrt::Windows::Devices::Geolocation::Geolocator statusGeolocator; + + winrt::Windows::Devices::Geolocation::PositionStatus m_currentStatus; +}; + +} // namespace geolocator_plugin diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_windows.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_windows.cpp new file mode 100755 index 00000000..dd1d1bcc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/geolocator_windows.cpp @@ -0,0 +1,12 @@ +#include "include/geolocator_windows/geolocator_windows.h" + +#include + +#include "geolocator_plugin.h" + +void GeolocatorWindowsRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + geolocator_plugin::GeolocatorPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/include/geolocator_windows/geolocator_windows.h b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/include/geolocator_windows/geolocator_windows.h new file mode 100755 index 00000000..6553e84c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/geolocator_windows/windows/include/geolocator_windows/geolocator_windows.h @@ -0,0 +1,23 @@ +#ifndef PACKAGES_GEOLOCATOR_GEOLOCATOR_WINDOWS_WINDOWS_INCLUDE_GEOLOCATOR_WINDOWS_GEOLOCATOR_plugin_H_ +#define PACKAGES_GEOLOCATOR_GEOLOCATOR_WINDOWS_WINDOWS_INCLUDE_GEOLOCATOR_WINDOWS_GEOLOCATOR_plugin_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void GeolocatorWindowsRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // PACKAGES_GEOLOCATOR_GEOLOCATOR_WINDOWS_WINDOWS_INCLUDE_GEOLOCATOR_WINDOWS_GEOLOCATOR_plugin_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows deleted file mode 120000 index e1d26ad8..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/image_picker_windows-0.2.1+1/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/AUTHORS b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/AUTHORS new file mode 100755 index 00000000..26e81c7f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/AUTHORS @@ -0,0 +1,7 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. +Alexandre Zollinger Chohfi diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/CHANGELOG.md new file mode 100755 index 00000000..732d91c7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/CHANGELOG.md @@ -0,0 +1,45 @@ +## 0.2.1+1 + +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. + +## 0.2.1 + +* Adds `getMedia` method. + +## 0.2.0 + +* Updates minimum Flutter version to 3.3. + +## 0.1.0+6 + +* Clarifies explanation of endorsement in README. +* Aligns Dart and Flutter SDK constraints. + +## 0.1.0+5 + +* Updates links for the merge of flutter/plugins into flutter/packages. + +## 0.1.0+4 + +* Updates example code for `use_build_context_synchronously` lint. +* Updates minimum Flutter version to 3.0. + +## 0.1.0+3 + +* Changes XTypeGroup initialization from final to const. +* Updates minimum Flutter version to 2.10. + +## 0.1.0+2 + +* Minor fixes for new analysis options. + +## 0.1.0+1 + +* Removes unnecessary imports. +* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors + lint warnings. + +## 0.1.0 + +* Initial Windows support. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/LICENSE new file mode 100755 index 00000000..c6823b81 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/README.md new file mode 100755 index 00000000..1aa30b17 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/README.md @@ -0,0 +1,27 @@ +# image\_picker\_windows + +A Windows implementation of [`image_picker`][1]. + +## Limitations + +`ImageSource.camera` is not supported unless a `cameraDelegate` is set. + +### pickImage() +The arguments `maxWidth`, `maxHeight`, and `imageQuality` are not currently supported. + +### pickVideo() +The argument `maxDuration` is not currently supported. + +## Usage + +### Import the package + +This package is [endorsed][2], which means you can simply use `file_selector` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. + +[1]: https://pub.dev/packages/image_picker +[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/README.md new file mode 100755 index 00000000..96b8bb17 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/lib/main.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/lib/main.dart new file mode 100755 index 00000000..8f488709 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/lib/main.dart @@ -0,0 +1,516 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; +import 'package:mime/mime.dart'; +import 'package:video_player/video_player.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + title: 'Image Picker Demo', + home: MyHomePage(title: 'Image Picker Example'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, this.title}); + + final String? title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + List? _mediaFileList; + + // This must be called from within a setState() callback + void _setImageFileListFromFile(XFile? value) { + _mediaFileList = value == null ? null : [value]; + } + + dynamic _pickImageError; + bool _isVideo = false; + + VideoPlayerController? _controller; + VideoPlayerController? _toBeDisposed; + String? _retrieveDataError; + + final ImagePickerPlatform _picker = ImagePickerPlatform.instance; + final TextEditingController maxWidthController = TextEditingController(); + final TextEditingController maxHeightController = TextEditingController(); + final TextEditingController qualityController = TextEditingController(); + + Future _playVideo(XFile? file) async { + if (file != null && mounted) { + await _disposeVideoController(); + final VideoPlayerController controller = + VideoPlayerController.file(File(file.path)); + _controller = controller; + await controller.setVolume(1.0); + await controller.initialize(); + await controller.setLooping(true); + await controller.play(); + setState(() {}); + } + } + + Future _onImageButtonPressed( + ImageSource source, { + required BuildContext context, + bool isMultiImage = false, + bool isMedia = false, + }) async { + if (_controller != null) { + await _controller!.setVolume(0.0); + } + if (context.mounted) { + if (_isVideo) { + final XFile? file = await _picker.getVideo( + source: source, maxDuration: const Duration(seconds: 10)); + await _playVideo(file); + } else if (isMultiImage) { + await _displayPickImageDialog(context, + (double? maxWidth, double? maxHeight, int? quality) async { + try { + final List pickedFileList = isMedia + ? await _picker.getMedia( + options: MediaOptions( + allowMultiple: isMultiImage, + imageOptions: ImageOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + )), + ) + : await _picker.getMultiImageWithOptions( + options: MultiImagePickerOptions( + imageOptions: ImageOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + ), + ), + ); + setState(() { + _mediaFileList = pickedFileList; + }); + } catch (e) { + setState(() { + _pickImageError = e; + }); + } + }); + } else if (isMedia) { + await _displayPickImageDialog(context, + (double? maxWidth, double? maxHeight, int? quality) async { + try { + final List pickedFileList = []; + final XFile? media = _firstOrNull(await _picker.getMedia( + options: MediaOptions( + allowMultiple: isMultiImage, + imageOptions: ImageOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + )), + )); + + if (media != null) { + pickedFileList.add(media); + setState(() { + _mediaFileList = pickedFileList; + }); + } + } catch (e) { + setState(() => _pickImageError = e); + } + }); + } else { + await _displayPickImageDialog(context, + (double? maxWidth, double? maxHeight, int? quality) async { + try { + final XFile? pickedFile = await _picker.getImageFromSource( + source: source, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + ), + ); + setState(() { + _setImageFileListFromFile(pickedFile); + }); + } catch (e) { + setState(() { + _pickImageError = e; + }); + } + }); + } + } + } + + @override + void deactivate() { + if (_controller != null) { + _controller!.setVolume(0.0); + _controller!.pause(); + } + super.deactivate(); + } + + @override + void dispose() { + _disposeVideoController(); + maxWidthController.dispose(); + maxHeightController.dispose(); + qualityController.dispose(); + super.dispose(); + } + + Future _disposeVideoController() async { + if (_toBeDisposed != null) { + await _toBeDisposed!.dispose(); + } + _toBeDisposed = _controller; + _controller = null; + } + + Widget _previewVideo() { + final Text? retrieveError = _getRetrieveErrorWidget(); + if (retrieveError != null) { + return retrieveError; + } + if (_controller == null) { + return const Text( + 'You have not yet picked a video', + textAlign: TextAlign.center, + ); + } + return Padding( + padding: const EdgeInsets.all(10.0), + child: AspectRatioVideo(_controller), + ); + } + + Widget _previewImages() { + final Text? retrieveError = _getRetrieveErrorWidget(); + if (retrieveError != null) { + return retrieveError; + } + if (_mediaFileList != null) { + return Semantics( + label: 'image_picker_example_picked_images', + child: ListView.builder( + key: UniqueKey(), + itemBuilder: (BuildContext context, int index) { + final String? mime = lookupMimeType(_mediaFileList![index].path); + return Semantics( + label: 'image_picker_example_picked_image', + child: mime == null || mime.startsWith('image/') + ? Image.file( + File(_mediaFileList![index].path), + errorBuilder: (BuildContext context, Object error, + StackTrace? stackTrace) { + return const Center( + child: Text('This image type is not supported')); + }, + ) + : _buildInlineVideoPlayer(index), + ); + }, + itemCount: _mediaFileList!.length, + ), + ); + } else if (_pickImageError != null) { + return Text( + 'Pick image error: $_pickImageError', + textAlign: TextAlign.center, + ); + } else { + return const Text( + 'You have not yet picked an image.', + textAlign: TextAlign.center, + ); + } + } + + Widget _buildInlineVideoPlayer(int index) { + final VideoPlayerController controller = + VideoPlayerController.file(File(_mediaFileList![index].path)); + const double volume = 1.0; + controller.setVolume(volume); + controller.initialize(); + controller.setLooping(true); + controller.play(); + return Center(child: AspectRatioVideo(controller)); + } + + Widget _handlePreview() { + if (_isVideo) { + return _previewVideo(); + } else { + return _previewImages(); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(widget.title!), + ), + body: Center( + child: _handlePreview(), + ), + floatingActionButton: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Semantics( + label: 'image_picker_example_from_gallery', + child: FloatingActionButton( + key: const Key('image_picker_example_from_gallery'), + onPressed: () { + _isVideo = false; + _onImageButtonPressed(ImageSource.gallery, context: context); + }, + heroTag: 'image0', + tooltip: 'Pick Image from gallery', + child: const Icon(Icons.photo), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + onPressed: () { + _isVideo = false; + _onImageButtonPressed( + ImageSource.gallery, + context: context, + isMultiImage: true, + isMedia: true, + ); + }, + heroTag: 'multipleMedia', + tooltip: 'Pick Multiple Media from gallery', + child: const Icon(Icons.photo_library), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + onPressed: () { + _isVideo = false; + _onImageButtonPressed( + ImageSource.gallery, + context: context, + isMedia: true, + ); + }, + heroTag: 'media', + tooltip: 'Pick Single Media from gallery', + child: const Icon(Icons.photo_library), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + onPressed: () { + _isVideo = false; + _onImageButtonPressed( + ImageSource.gallery, + context: context, + isMultiImage: true, + ); + }, + heroTag: 'image1', + tooltip: 'Pick Multiple Image from gallery', + child: const Icon(Icons.photo_library), + ), + ), + if (_picker.supportsImageSource(ImageSource.camera)) + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + onPressed: () { + _isVideo = false; + _onImageButtonPressed(ImageSource.camera, context: context); + }, + heroTag: 'image2', + tooltip: 'Take a Photo', + child: const Icon(Icons.camera_alt), + ), + ), + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + backgroundColor: Colors.red, + onPressed: () { + _isVideo = true; + _onImageButtonPressed(ImageSource.gallery, context: context); + }, + heroTag: 'video0', + tooltip: 'Pick Video from gallery', + child: const Icon(Icons.video_library), + ), + ), + if (_picker.supportsImageSource(ImageSource.camera)) + Padding( + padding: const EdgeInsets.only(top: 16.0), + child: FloatingActionButton( + backgroundColor: Colors.red, + onPressed: () { + _isVideo = true; + _onImageButtonPressed(ImageSource.camera, context: context); + }, + heroTag: 'video1', + tooltip: 'Take a Video', + child: const Icon(Icons.videocam), + ), + ), + ], + ), + ); + } + + Text? _getRetrieveErrorWidget() { + if (_retrieveDataError != null) { + final Text result = Text(_retrieveDataError!); + _retrieveDataError = null; + return result; + } + return null; + } + + Future _displayPickImageDialog( + BuildContext context, OnPickImageCallback onPick) async { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Add optional parameters'), + content: Column( + children: [ + TextField( + controller: maxWidthController, + keyboardType: + const TextInputType.numberWithOptions(decimal: true), + decoration: const InputDecoration( + hintText: 'Enter maxWidth if desired'), + ), + TextField( + controller: maxHeightController, + keyboardType: + const TextInputType.numberWithOptions(decimal: true), + decoration: const InputDecoration( + hintText: 'Enter maxHeight if desired'), + ), + TextField( + controller: qualityController, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + hintText: 'Enter quality if desired'), + ), + ], + ), + actions: [ + TextButton( + child: const Text('CANCEL'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: const Text('PICK'), + onPressed: () { + final double? width = maxWidthController.text.isNotEmpty + ? double.parse(maxWidthController.text) + : null; + final double? height = maxHeightController.text.isNotEmpty + ? double.parse(maxHeightController.text) + : null; + final int? quality = qualityController.text.isNotEmpty + ? int.parse(qualityController.text) + : null; + onPick(width, height, quality); + Navigator.of(context).pop(); + }), + ], + ); + }); + } +} + +typedef OnPickImageCallback = void Function( + double? maxWidth, double? maxHeight, int? quality); + +class AspectRatioVideo extends StatefulWidget { + const AspectRatioVideo(this.controller, {super.key}); + + final VideoPlayerController? controller; + + @override + AspectRatioVideoState createState() => AspectRatioVideoState(); +} + +class AspectRatioVideoState extends State { + VideoPlayerController? get controller => widget.controller; + bool initialized = false; + + void _onVideoControllerUpdate() { + if (!mounted) { + return; + } + if (initialized != controller!.value.isInitialized) { + initialized = controller!.value.isInitialized; + setState(() {}); + } + } + + @override + void initState() { + super.initState(); + controller!.addListener(_onVideoControllerUpdate); + } + + @override + void dispose() { + controller!.removeListener(_onVideoControllerUpdate); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (initialized) { + return Center( + child: AspectRatio( + aspectRatio: controller!.value.aspectRatio, + child: VideoPlayer(controller!), + ), + ); + } else { + return Container(); + } + } +} + +T? _firstOrNull(List list) { + return list.isEmpty ? null : list.first; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/pubspec.yaml new file mode 100755 index 00000000..f3fb1ed0 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/pubspec.yaml @@ -0,0 +1,29 @@ +name: example +description: Example for image_picker_windows implementation. +publish_to: 'none' +version: 1.0.0 + +environment: + sdk: ">=2.19.0 <4.0.0" + flutter: ">=3.7.0" + +dependencies: + flutter: + sdk: flutter + image_picker_platform_interface: ^2.8.0 + image_picker_windows: + # When depending on this package from a real application you should use: + # image_picker_windows: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: .. + mime: ^1.0.4 + video_player: ^2.1.4 + +dev_dependencies: + flutter_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/CMakeLists.txt new file mode 100755 index 00000000..1633297a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.14) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..b2e4bd8d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/flutter/generated_plugins.cmake b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/flutter/generated_plugins.cmake new file mode 100755 index 00000000..a423a024 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..de2d8916 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/Runner.rc b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/Runner.rc new file mode 100755 index 00000000..5fdea291 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/flutter_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..8254bd9f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/flutter_window.cpp @@ -0,0 +1,65 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/flutter_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..f1fc6690 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/flutter_window.h @@ -0,0 +1,37 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/main.cpp new file mode 100755 index 00000000..df379fa0 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/main.cpp @@ -0,0 +1,46 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t* command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/resource.h b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/resources/app_icon.ico b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/resources/app_icon.ico differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/runner.exe.manifest b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/utils.cpp new file mode 100755 index 00000000..fb7e945a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/utils.cpp @@ -0,0 +1,67 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE* unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/utils.h new file mode 100755 index 00000000..bd81e1e0 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/utils.h @@ -0,0 +1,23 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/win32_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..85aa3614 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/win32_window.cpp @@ -0,0 +1,241 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/win32_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/win32_window.h new file mode 100755 index 00000000..d2a73005 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/example/windows/runner/win32_window.h @@ -0,0 +1,99 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/lib/image_picker_windows.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/lib/image_picker_windows.dart new file mode 100755 index 00000000..e9e41462 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/lib/image_picker_windows.dart @@ -0,0 +1,210 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:file_selector_windows/file_selector_windows.dart'; +import 'package:flutter/foundation.dart'; +import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; + +/// The Windows implementation of [ImagePickerPlatform]. +/// +/// This class implements the `package:image_picker` functionality for +/// Windows. +class ImagePickerWindows extends CameraDelegatingImagePickerPlatform { + /// Constructs a ImagePickerWindows. + ImagePickerWindows(); + + /// List of image extensions used when picking images + @visibleForTesting + static const List imageFormats = [ + 'jpg', + 'jpeg', + 'png', + 'bmp', + 'webp', + 'gif', + 'tif', + 'tiff', + 'apng' + ]; + + /// List of video extensions used when picking videos + @visibleForTesting + static const List videoFormats = [ + 'mov', + 'wmv', + 'mkv', + 'mp4', + 'webm', + 'avi', + 'mpeg', + 'mpg' + ]; + + /// The file selector used to prompt the user to select images or videos. + @visibleForTesting + static FileSelectorPlatform fileSelector = FileSelectorWindows(); + + /// Registers this class as the default instance of [ImagePickerPlatform]. + static void registerWith() { + ImagePickerPlatform.instance = ImagePickerWindows(); + } + + // This is soft-deprecated in the platform interface, and is only implemented + // for compatibility. Callers should be using getImageFromSource. + @override + Future pickImage({ + required ImageSource source, + double? maxWidth, + double? maxHeight, + int? imageQuality, + CameraDevice preferredCameraDevice = CameraDevice.rear, + }) async { + final XFile? file = await getImageFromSource( + source: source, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice)); + if (file != null) { + return PickedFile(file.path); + } + return null; + } + + // This is soft-deprecated in the platform interface, and is only implemented + // for compatibility. Callers should be using getVideo. + @override + Future pickVideo({ + required ImageSource source, + CameraDevice preferredCameraDevice = CameraDevice.rear, + Duration? maxDuration, + }) async { + final XFile? file = await getVideo( + source: source, + preferredCameraDevice: preferredCameraDevice, + maxDuration: maxDuration); + if (file != null) { + return PickedFile(file.path); + } + return null; + } + + // This is soft-deprecated in the platform interface, and is only implemented + // for compatibility. Callers should be using getImageFromSource. + @override + Future getImage({ + required ImageSource source, + double? maxWidth, + double? maxHeight, + int? imageQuality, + CameraDevice preferredCameraDevice = CameraDevice.rear, + }) async { + return getImageFromSource( + source: source, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice)); + } + + // [ImagePickerOptions] options are not currently supported. If any + // of its fields are set, they will be silently ignored. + // + // If source is `ImageSource.camera`, a `StateError` will be thrown + // unless a [cameraDelegate] is set. + @override + Future getImageFromSource({ + required ImageSource source, + ImagePickerOptions options = const ImagePickerOptions(), + }) async { + switch (source) { + case ImageSource.camera: + return super.getImageFromSource(source: source); + case ImageSource.gallery: + const XTypeGroup typeGroup = + XTypeGroup(label: 'Images', extensions: imageFormats); + final XFile? file = await fileSelector + .openFile(acceptedTypeGroups: [typeGroup]); + return file; + } + // Ensure that there's a fallback in case a new source is added. + // ignore: dead_code + throw UnimplementedError('Unknown ImageSource: $source'); + } + + // `preferredCameraDevice` and `maxDuration` arguments are not currently + // supported. If either of these arguments are supplied, they will be silently + // ignored. + // + // If source is `ImageSource.camera`, a `StateError` will be thrown + // unless a [cameraDelegate] is set. + @override + Future getVideo({ + required ImageSource source, + CameraDevice preferredCameraDevice = CameraDevice.rear, + Duration? maxDuration, + }) async { + switch (source) { + case ImageSource.camera: + return super.getVideo( + source: source, + preferredCameraDevice: preferredCameraDevice, + maxDuration: maxDuration); + case ImageSource.gallery: + const XTypeGroup typeGroup = + XTypeGroup(label: 'Videos', extensions: videoFormats); + final XFile? file = await fileSelector + .openFile(acceptedTypeGroups: [typeGroup]); + return file; + } + // Ensure that there's a fallback in case a new source is added. + // ignore: dead_code + throw UnimplementedError('Unknown ImageSource: $source'); + } + + // `maxWidth`, `maxHeight`, and `imageQuality` arguments are not currently + // supported. If any of these arguments are supplied, they will be silently + // ignored. + @override + Future> getMultiImage({ + double? maxWidth, + double? maxHeight, + int? imageQuality, + }) async { + const XTypeGroup typeGroup = + XTypeGroup(label: 'Images', extensions: imageFormats); + final List files = await fileSelector + .openFiles(acceptedTypeGroups: [typeGroup]); + return files; + } + + // `maxWidth`, `maxHeight`, and `imageQuality` arguments are not + // supported on Windows. If any of these arguments is supplied, + // they will be silently ignored by the Windows version of the plugin. + @override + Future> getMedia({required MediaOptions options}) async { + const XTypeGroup typeGroup = XTypeGroup( + label: 'images and videos', + extensions: [...imageFormats, ...videoFormats]); + + List files; + + if (options.allowMultiple) { + files = await fileSelector + .openFiles(acceptedTypeGroups: [typeGroup]); + } else { + final XFile? file = await fileSelector + .openFile(acceptedTypeGroups: [typeGroup]); + files = [ + if (file != null) file, + ]; + } + return files; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/pubspec.yaml new file mode 100755 index 00000000..90d9d9fc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/pubspec.yaml @@ -0,0 +1,34 @@ +name: image_picker_windows +description: Windows platform implementation of image_picker +repository: https://github.com/flutter/packages/tree/main/packages/image_picker/image_picker_windows +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 +version: 0.2.1+1 + +environment: + sdk: ">=2.19.0 <4.0.0" + flutter: ">=3.7.0" + +flutter: + plugin: + implements: image_picker + platforms: + windows: + dartPluginClass: ImagePickerWindows + +dependencies: + file_selector_platform_interface: ^2.2.0 + file_selector_windows: ^0.9.0 + flutter: + sdk: flutter + image_picker_platform_interface: ^2.8.0 + +dev_dependencies: + build_runner: ^2.1.5 + flutter_test: + sdk: flutter + mockito: 5.4.1 + +topics: + - image-picker + - files + - file-selection diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/test/image_picker_windows_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/test/image_picker_windows_test.dart new file mode 100755 index 00000000..6da0873a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/test/image_picker_windows_test.dart @@ -0,0 +1,187 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; +import 'package:image_picker_windows/image_picker_windows.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'image_picker_windows_test.mocks.dart'; + +@GenerateMocks([FileSelectorPlatform]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + // Returns the captured type groups from a mock call result, assuming that + // exactly one call was made and only the type groups were captured. + List capturedTypeGroups(VerificationResult result) { + return result.captured.single as List; + } + + group('ImagePickerWindows', () { + late ImagePickerWindows plugin; + late MockFileSelectorPlatform mockFileSelectorPlatform; + + setUp(() { + plugin = ImagePickerWindows(); + mockFileSelectorPlatform = MockFileSelectorPlatform(); + + when(mockFileSelectorPlatform.openFile( + acceptedTypeGroups: anyNamed('acceptedTypeGroups'))) + .thenAnswer((_) async => null); + + when(mockFileSelectorPlatform.openFiles( + acceptedTypeGroups: anyNamed('acceptedTypeGroups'))) + .thenAnswer((_) async => List.empty()); + + ImagePickerWindows.fileSelector = mockFileSelectorPlatform; + }); + + test('registered instance', () { + ImagePickerWindows.registerWith(); + expect(ImagePickerPlatform.instance, isA()); + }); + + group('images', () { + test('pickImage passes the accepted type groups correctly', () async { + await plugin.pickImage(source: ImageSource.gallery); + + final VerificationResult result = verify( + mockFileSelectorPlatform.openFile( + acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].extensions, + ImagePickerWindows.imageFormats); + }); + + test('getImage passes the accepted type groups correctly', () async { + await plugin.getImage(source: ImageSource.gallery); + + final VerificationResult result = verify( + mockFileSelectorPlatform.openFile( + acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].extensions, + ImagePickerWindows.imageFormats); + }); + + test('getMultiImage passes the accepted type groups correctly', () async { + await plugin.getMultiImage(); + + final VerificationResult result = verify( + mockFileSelectorPlatform.openFiles( + acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].extensions, + ImagePickerWindows.imageFormats); + }); + + test( + 'getImageFromSource throws StateError when source is camera with no delegate', + () async { + await expectLater(plugin.getImageFromSource(source: ImageSource.camera), + throwsStateError); + }); + + test('getMultiImage passes the accepted type groups correctly', () async { + await plugin.getMultiImage(); + + final VerificationResult result = verify( + mockFileSelectorPlatform.openFiles( + acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].extensions, + ImagePickerWindows.imageFormats); + }); + }); + + group('videos', () { + test('pickVideo passes the accepted type groups correctly', () async { + await plugin.pickVideo(source: ImageSource.gallery); + + final VerificationResult result = verify( + mockFileSelectorPlatform.openFile( + acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].extensions, + ImagePickerWindows.videoFormats); + }); + + test('getVideo passes the accepted type groups correctly', () async { + await plugin.getVideo(source: ImageSource.gallery); + + final VerificationResult result = verify( + mockFileSelectorPlatform.openFile( + acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].extensions, + ImagePickerWindows.videoFormats); + }); + + test('getVideo calls delegate when source is camera', () async { + const String fakePath = '/tmp/foo'; + plugin.cameraDelegate = FakeCameraDelegate(result: XFile(fakePath)); + expect((await plugin.getVideo(source: ImageSource.camera))!.path, + fakePath); + }); + + test('getVideo throws StateError when source is camera with no delegate', + () async { + await expectLater( + plugin.getVideo(source: ImageSource.camera), throwsStateError); + }); + }); + + group('media', () { + test('getMedia passes the accepted type groups correctly', () async { + await plugin.getMedia(options: const MediaOptions(allowMultiple: true)); + + final VerificationResult result = verify( + mockFileSelectorPlatform.openFiles( + acceptedTypeGroups: captureAnyNamed('acceptedTypeGroups'))); + expect(capturedTypeGroups(result)[0].extensions, [ + ...ImagePickerWindows.imageFormats, + ...ImagePickerWindows.videoFormats + ]); + }); + + test('multiple media handles an empty path response gracefully', + () async { + expect( + await plugin.getMedia( + options: const MediaOptions( + allowMultiple: true, + ), + ), + []); + }); + + test('single media handles an empty path response gracefully', () async { + expect( + await plugin.getMedia( + options: const MediaOptions( + allowMultiple: false, + ), + ), + []); + }); + }); + }); +} + +class FakeCameraDelegate extends ImagePickerCameraDelegate { + FakeCameraDelegate({this.result}); + + XFile? result; + + @override + Future takePhoto( + {ImagePickerCameraDelegateOptions options = + const ImagePickerCameraDelegateOptions()}) async { + return result; + } + + @override + Future takeVideo( + {ImagePickerCameraDelegateOptions options = + const ImagePickerCameraDelegateOptions()}) async { + return result; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/test/image_picker_windows_test.mocks.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/test/image_picker_windows_test.mocks.dart new file mode 100755 index 00000000..32fb3802 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/image_picker_windows/test/image_picker_windows_test.mocks.dart @@ -0,0 +1,120 @@ +// Mocks generated by Mockito 5.4.0 from annotations +// in image_picker_windows/test/image_picker_windows_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:file_selector_platform_interface/file_selector_platform_interface.dart' + as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class + +/// A class which mocks [FileSelectorPlatform]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFileSelectorPlatform extends _i1.Mock + implements _i2.FileSelectorPlatform { + MockFileSelectorPlatform() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future<_i2.XFile?> openFile({ + List<_i2.XTypeGroup>? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #openFile, + [], + { + #acceptedTypeGroups: acceptedTypeGroups, + #initialDirectory: initialDirectory, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future<_i2.XFile?>.value(), + ) as _i3.Future<_i2.XFile?>); + @override + _i3.Future> openFiles({ + List<_i2.XTypeGroup>? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #openFiles, + [], + { + #acceptedTypeGroups: acceptedTypeGroups, + #initialDirectory: initialDirectory, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future>.value(<_i2.XFile>[]), + ) as _i3.Future>); + @override + _i3.Future getSavePath({ + List<_i2.XTypeGroup>? acceptedTypeGroups, + String? initialDirectory, + String? suggestedName, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #getSavePath, + [], + { + #acceptedTypeGroups: acceptedTypeGroups, + #initialDirectory: initialDirectory, + #suggestedName: suggestedName, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + @override + _i3.Future getDirectoryPath({ + String? initialDirectory, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #getDirectoryPath, + [], + { + #initialDirectory: initialDirectory, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future.value(), + ) as _i3.Future); + @override + _i3.Future> getDirectoryPaths({ + String? initialDirectory, + String? confirmButtonText, + }) => + (super.noSuchMethod( + Invocation.method( + #getDirectoryPaths, + [], + { + #initialDirectory: initialDirectory, + #confirmButtonText: confirmButtonText, + }, + ), + returnValue: _i3.Future>.value([]), + ) as _i3.Future>); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows deleted file mode 120000 index c60af49d..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/AUTHORS b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/AUTHORS new file mode 100755 index 00000000..493a0b4e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/AUTHORS @@ -0,0 +1,66 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. +The Chromium Authors +German Saprykin +Benjamin Sauer +larsenthomasj@gmail.com +Ali Bitek +Pol Batlló +Anatoly Pulyaevskiy +Hayden Flinner +Stefano Rodriguez +Salvatore Giordano +Brian Armstrong +Paul DeMarco +Fabricio Nogueira +Simon Lightfoot +Ashton Thomas +Thomas Danner +Diego Velásquez +Hajime Nakamura +Tuyển Vũ Xuân +Miguel Ruivo +Sarthak Verma +Mike Diarmid +Invertase +Elliot Hesp +Vince Varga +Aawaz Gyawali +EUI Limited +Katarina Sheremet +Thomas Stockx +Sarbagya Dhaubanjar +Ozkan Eksi +Rishab Nayak +ko2ic +Jonathan Younger +Jose Sanchez +Debkanchan Samadder +Audrius Karosevicius +Lukasz Piliszczuk +SoundReply Solutions GmbH +Rafal Wachol +Pau Picas +Christian Weder +Alexandru Tuca +Christian Weder +Rhodes Davis Jr. +Luigi Agosti +Quentin Le Guennec +Koushik Ravikumar +Nissim Dsilva +Giancarlo Rocha +Ryo Miyake +Théo Champion +Kazuki Yamaguchi +Eitan Schwartz +Chris Rutkowski +Juan Alvarez +Aleksandr Yurkovskiy +Anton Borries +Alex Li +Rahul Raj <64.rahulraj@gmail.com> diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/CHANGELOG.md new file mode 100755 index 00000000..46e7ac64 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/CHANGELOG.md @@ -0,0 +1,123 @@ +## 2.3.0 + +* Replaces `win32` dependency with direct FFI usage. +* Updates minimum supported SDK version to Flutter 3.16/Dart 3.2. + +## 2.2.1 + +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. + +## 2.2.0 + +* Adds getApplicationCachePath() for storing app-specific cache files. + +## 2.1.7 + +* Adds compatibility with `win32` 5.x. +* Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. + +## 2.1.6 + +* Adds compatibility with `win32` 4.x. + +## 2.1.5 + +* Clarifies explanation of endorsement in README. +* Aligns Dart and Flutter SDK constraints. + +## 2.1.4 + +* Updates links for the merge of flutter/plugins into flutter/packages. +* Updates minimum Flutter version to 3.0. + +## 2.1.3 + +* Updates minimum Flutter version to 2.10. +* Adds compatibility with `package:win32` 3.x. + +## 2.1.2 + +* Fixes avoid_redundant_argument_values lint warnings and minor typos. + +## 2.1.1 + +* Updates dependency version of `package:win32` to 2.1.0. + +## 2.1.0 + +* Upgrades `package:ffi` dependency to 2.0.0. +* Added support for unicode encoded VERSIONINFO. +* Minor fixes for new analysis options. + +## 2.0.6 + +* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors + lint warnings. + +## 2.0.5 + +* Removes dependency on `meta`. + +## 2.0.4 + +* Removed obsolete `pluginClass: none` from pubpsec. + +## 2.0.3 + +* Updated installation instructions in README. + +## 2.0.2 + +* Add `implements` to pubspec.yaml. +* Add `registerWith()` to the Dart main class. + +## 2.0.1 + +* Fix a crash when a known folder can't be located. + +## 2.0.0 + +* Migrate to null safety + +## 0.0.4+4 + +* Update Flutter SDK constraint. + +## 0.0.4+3 + +* Remove unused `test` dependency. +* Update Dart SDK constraint in example. + +## 0.0.4+2 + +* Check in windows/ directory for example/ + +## 0.0.4+1 + +* Add getPath to the stub, so that the analyzer won't complain about + fakes that override it. +* export 'folders.dart' rather than importing it, since it's intended to be + public. + +## 0.0.4 + +* Move the actual implementation behind a conditional import, exporting + a stub for platforms that don't support FFI. Fixes web builds in + projects with transitive dependencies on path_provider. + +## 0.0.3 + +* Add missing `pluginClass: none` for compatibilty with stable channel. + +## 0.0.2 + +* README update for endorsement. +* Changed getApplicationSupportPath location. +* Removed getLibraryPath. + +## 0.0.1+2 + +* The initial implementation of path_provider for Windows + * Implements getTemporaryPath, getApplicationSupportPath, getLibraryPath, + getApplicationDocumentsPath and getDownloadsPath. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/LICENSE new file mode 100755 index 00000000..c6823b81 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/README.md new file mode 100755 index 00000000..0aeb4039 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/README.md @@ -0,0 +1,15 @@ +# path\_provider\_windows + +The Windows implementation of [`path_provider`][1]. + +## Usage + +This package is [endorsed][2], which means you can simply use `path_provider` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. + +[1]: https://pub.dev/packages/path_provider +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/README.md new file mode 100755 index 00000000..96b8bb17 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/integration_test/path_provider_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/integration_test/path_provider_test.dart new file mode 100755 index 00000000..0e900224 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/integration_test/path_provider_test.dart @@ -0,0 +1,63 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:path_provider_windows/path_provider_windows.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('getTemporaryDirectory', (WidgetTester tester) async { + final PathProviderWindows provider = PathProviderWindows(); + final String? result = await provider.getTemporaryPath(); + _verifySampleFile(result, 'temporaryDirectory'); + }); + + testWidgets('getApplicationDocumentsDirectory', (WidgetTester tester) async { + final PathProviderWindows provider = PathProviderWindows(); + final String? result = await provider.getApplicationDocumentsPath(); + _verifySampleFile(result, 'applicationDocuments'); + }); + + testWidgets('getApplicationSupportDirectory', (WidgetTester tester) async { + final PathProviderWindows provider = PathProviderWindows(); + final String? result = await provider.getApplicationSupportPath(); + _verifySampleFile(result, 'applicationSupport'); + }); + + testWidgets('getApplicationCacheDirectory', (WidgetTester tester) async { + final PathProviderWindows provider = PathProviderWindows(); + final String? result = await provider.getApplicationCachePath(); + _verifySampleFile(result, 'applicationCache'); + }); + + testWidgets('getDownloadsDirectory', (WidgetTester tester) async { + final PathProviderWindows provider = PathProviderWindows(); + final String? result = await provider.getDownloadsPath(); + _verifySampleFile(result, 'downloads'); + }); +} + +/// Verify a file called [name] in [directoryPath] by recreating it with test +/// contents when necessary. +void _verifySampleFile(String? directoryPath, String name) { + expect(directoryPath, isNotNull); + if (directoryPath == null) { + return; + } + final Directory directory = Directory(directoryPath); + final File file = File('${directory.path}${Platform.pathSeparator}$name'); + + if (file.existsSync()) { + file.deleteSync(); + expect(file.existsSync(), isFalse); + } + + file.writeAsStringSync('Hello world!'); + expect(file.readAsStringSync(), 'Hello world!'); + expect(directory.listSync(), isNotEmpty); + file.deleteSync(); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/lib/main.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/lib/main.dart new file mode 100755 index 00000000..53e46e51 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/lib/main.dart @@ -0,0 +1,103 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'package:flutter/material.dart'; +import 'package:path_provider_windows/path_provider_windows.dart'; + +void main() { + runApp(const MyApp()); +} + +/// Sample app +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + String? _tempDirectory = 'Unknown'; + String? _downloadsDirectory = 'Unknown'; + String? _appSupportDirectory = 'Unknown'; + String? _documentsDirectory = 'Unknown'; + String? _cacheDirectory = 'Unknown'; + + @override + void initState() { + super.initState(); + initDirectories(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future initDirectories() async { + String? tempDirectory; + String? downloadsDirectory; + String? appSupportDirectory; + String? documentsDirectory; + String? cacheDirectory; + final PathProviderWindows provider = PathProviderWindows(); + + try { + tempDirectory = await provider.getTemporaryPath(); + } catch (exception) { + tempDirectory = 'Failed to get temp directory: $exception'; + } + try { + downloadsDirectory = await provider.getDownloadsPath(); + } catch (exception) { + downloadsDirectory = 'Failed to get downloads directory: $exception'; + } + + try { + documentsDirectory = await provider.getApplicationDocumentsPath(); + } catch (exception) { + documentsDirectory = 'Failed to get documents directory: $exception'; + } + + try { + appSupportDirectory = await provider.getApplicationSupportPath(); + } catch (exception) { + appSupportDirectory = 'Failed to get app support directory: $exception'; + } + + try { + cacheDirectory = await provider.getApplicationCachePath(); + } catch (exception) { + cacheDirectory = 'Failed to get cache directory: $exception'; + } + + setState(() { + _tempDirectory = tempDirectory; + _downloadsDirectory = downloadsDirectory; + _appSupportDirectory = appSupportDirectory; + _documentsDirectory = documentsDirectory; + _cacheDirectory = cacheDirectory; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Path Provider example app'), + ), + body: Center( + child: Column( + children: [ + Text('Temp Directory: $_tempDirectory\n'), + Text('Documents Directory: $_documentsDirectory\n'), + Text('Downloads Directory: $_downloadsDirectory\n'), + Text('Application Support Directory: $_appSupportDirectory\n'), + Text('Cache Directory: $_cacheDirectory\n'), + ], + ), + ), + ), + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/pubspec.yaml new file mode 100755 index 00000000..632615bf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/pubspec.yaml @@ -0,0 +1,27 @@ +name: path_provider_example +description: Demonstrates how to use the path_provider plugin. +publish_to: none + +environment: + sdk: ^3.2.0 + flutter: ">=3.16.0" + +dependencies: + flutter: + sdk: flutter + path_provider_windows: + # When depending on this package from a real application you should use: + # path_provider_windows: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/test_driver/integration_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/test_driver/integration_test.dart new file mode 100755 index 00000000..4f10f2a5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/CMakeLists.txt new file mode 100755 index 00000000..abf90408 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.15) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..0a917772 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,107 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/flutter/generated_plugins.cmake b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/flutter/generated_plugins.cmake new file mode 100755 index 00000000..b93c4c30 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..977e38b5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/Runner.rc b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/Runner.rc new file mode 100755 index 00000000..41d1b5cf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2020 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/flutter_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..8e415602 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/flutter_window.cpp @@ -0,0 +1,68 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop* run_loop, + const flutter::DartProject& project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opporutunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/flutter_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..8e9c12bb --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/flutter_window.h @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "run_loop.h" +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop* run_loop, + const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The run loop driving events for this window. + RunLoop* run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/main.cpp new file mode 100755 index 00000000..c7dbde1c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/main.cpp @@ -0,0 +1,40 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t* command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/resource.h b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/resources/app_icon.ico b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/resources/app_icon.ico differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/run_loop.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/run_loop.cpp new file mode 100755 index 00000000..1916500e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/run_loop.cpp @@ -0,0 +1,70 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "run_loop.h" + +#include + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterEngine* flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterEngine* flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto instance : flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/run_loop.h b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/run_loop.h new file mode 100755 index 00000000..819ed3ed --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/run_loop.h @@ -0,0 +1,42 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_RUN_LOOP_H_ +#define RUNNER_RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { + public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const&) = delete; + RunLoop& operator=(RunLoop const&) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine* flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine* flutter_instance); + + private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUNNER_RUN_LOOP_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/runner.exe.manifest b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/utils.cpp new file mode 100755 index 00000000..e875ce8b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/utils.cpp @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE* unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/utils.h new file mode 100755 index 00000000..16b3f079 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/utils.h @@ -0,0 +1,12 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/win32_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..a609a200 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/win32_window.cpp @@ -0,0 +1,240 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/win32_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/win32_window.h new file mode 100755 index 00000000..d2a73005 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/example/windows/runner/win32_window.h @@ -0,0 +1,99 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/path_provider_windows.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/path_provider_windows.dart new file mode 100755 index 00000000..9af55ac2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/path_provider_windows.dart @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// path_provider_windows is implemented using FFI; export a stub for platforms +// that don't support FFI (e.g., web) to avoid having transitive dependencies +// break web compilation. +export 'src/folders_stub.dart' if (dart.library.ffi) 'src/folders.dart'; +export 'src/path_provider_windows_stub.dart' + if (dart.library.ffi) 'src/path_provider_windows_real.dart'; diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/folders.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/folders.dart new file mode 100755 index 00000000..022aba45 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/folders.dart @@ -0,0 +1,250 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: non_constant_identifier_names + +// ignore: avoid_classes_with_only_static_members +/// A class containing the GUID references for each of the documented Windows +/// known folders. A property of this class may be passed to the `getPath` +/// method in the [PathProvidersWindows] class to retrieve a known folder from +/// Windows. +// These constants come from +// https://learn.microsoft.com/windows/win32/shell/knownfolderid +class WindowsKnownFolder { + /// The file system directory that is used to store administrative tools for + /// an individual user. The MMC will save customized consoles to this + /// directory, and it will roam with the user. + static String get AdminTools => '{724EF170-A42D-4FEF-9F26-B60E846FBA4F}'; + + /// The file system directory that acts as a staging area for files waiting to + /// be written to a CD. A typical path is C:\Documents and + /// Settings\username\Local Settings\Application Data\Microsoft\CD Burning. + static String get CDBurning => '{9E52AB10-F80D-49DF-ACB8-4330F5687855}'; + + /// The file system directory that contains administrative tools for all users + /// of the computer. + static String get CommonAdminTools => + '{D0384E7D-BAC3-4797-8F14-CBA229B392B5}'; + + /// The file system directory that contains the directories for the common + /// program groups that appear on the Start menu for all users. A typical path + /// is C:\Documents and Settings\All Users\Start Menu\Programs. + static String get CommonPrograms => '{0139D44E-6AFE-49F2-8690-3DAFCAE6FFB8}'; + + /// The file system directory that contains the programs and folders that + /// appear on the Start menu for all users. A typical path is C:\Documents and + /// Settings\All Users\Start Menu. + static String get CommonStartMenu => '{A4115719-D62E-491D-AA7C-E74B8BE3B067}'; + + /// The file system directory that contains the programs that appear in the + /// Startup folder for all users. A typical path is C:\Documents and + /// Settings\All Users\Start Menu\Programs\Startup. + static String get CommonStartup => '{82A5EA35-D9CD-47C5-9629-E15D2F714E6E}'; + + /// The file system directory that contains the templates that are available + /// to all users. A typical path is C:\Documents and Settings\All + /// Users\Templates. + static String get CommonTemplates => '{B94237E7-57AC-4347-9151-B08C6C32D1F7}'; + + /// The virtual folder that represents My Computer, containing everything on + /// the local computer: storage devices, printers, and Control Panel. The + /// folder can also contain mapped network drives. + static String get ComputerFolder => '{0AC0837C-BBF8-452A-850D-79D08E667CA7}'; + + /// The virtual folder that represents Network Connections, that contains + /// network and dial-up connections. + static String get ConnectionsFolder => + '{6F0CD92B-2E97-45D1-88FF-B0D186B8DEDD}'; + + /// The virtual folder that contains icons for the Control Panel applications. + static String get ControlPanelFolder => + '{82A74AEB-AEB4-465C-A014-D097EE346D63}'; + + /// The file system directory that serves as a common repository for Internet + /// cookies. A typical path is C:\Documents and Settings\username\Cookies. + static String get Cookies => '{2B0F765D-C0E9-4171-908E-08A611B84FF6}'; + + /// The virtual folder that represents the Windows desktop, the root of the + /// namespace. + static String get Desktop => '{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}'; + + /// The virtual folder that represents the My Documents desktop item. + static String get Documents => '{FDD39AD0-238F-46AF-ADB4-6C85480369C7}'; + + /// The file system directory that serves as a repository for Internet + /// downloads. + static String get Downloads => '{374DE290-123F-4565-9164-39C4925E467B}'; + + /// The file system directory that serves as a common repository for the + /// user's favorite items. A typical path is C:\Documents and + /// Settings\username\Favorites. + static String get Favorites => '{1777F761-68AD-4D8A-87BD-30B759FA33DD}'; + + /// A virtual folder that contains fonts. A typical path is C:\Windows\Fonts. + static String get Fonts => '{FD228CB7-AE11-4AE3-864C-16F3910AB8FE}'; + + /// The file system directory that serves as a common repository for Internet + /// history items. + static String get History => '{D9DC8A3B-B784-432E-A781-5A1130A75963}'; + + /// The file system directory that serves as a common repository for temporary + /// Internet files. A typical path is C:\Documents and Settings\username\Local + /// Settings\Temporary Internet Files. + static String get InternetCache => '{352481E8-33BE-4251-BA85-6007CAEDCF9D}'; + + /// A virtual folder for Internet Explorer. + static String get InternetFolder => '{4D9F7874-4E0C-4904-967B-40B0D20C3E4B}'; + + /// The file system directory that serves as a data repository for local + /// (nonroaming) applications. A typical path is C:\Documents and + /// Settings\username\Local Settings\Application Data. + static String get LocalAppData => '{F1B32785-6FBA-4FCF-9D55-7B8E7F157091}'; + + /// The file system directory that serves as a common repository for music + /// files. A typical path is C:\Documents and Settings\User\My Documents\My + /// Music. + static String get Music => '{4BD8D571-6D19-48D3-BE97-422220080E43}'; + + /// A file system directory that contains the link objects that may exist in + /// the My Network Places virtual folder. A typical path is C:\Documents and + /// Settings\username\NetHood. + static String get NetHood => '{C5ABBF53-E17F-4121-8900-86626FC2C973}'; + + /// The folder that represents other computers in your workgroup. + static String get NetworkFolder => '{D20BEEC4-5CA8-4905-AE3B-BF251EA09B53}'; + + /// The file system directory that serves as a common repository for image + /// files. A typical path is C:\Documents and Settings\username\My + /// Documents\My Pictures. + static String get Pictures => '{33E28130-4E1E-4676-835A-98395C3BC3BB}'; + + /// The file system directory that contains the link objects that can exist in + /// the Printers virtual folder. A typical path is C:\Documents and + /// Settings\username\PrintHood. + static String get PrintHood => '{9274BD8D-CFD1-41C3-B35E-B13F55A758F4}'; + + /// The virtual folder that contains installed printers. + static String get PrintersFolder => '{76FC4E2D-D6AD-4519-A663-37BD56068185}'; + + /// The user's profile folder. A typical path is C:\Users\username. + /// Applications should not create files or folders at this level. + static String get Profile => '{5E6C858F-0E22-4760-9AFE-EA3317B67173}'; + + /// The file system directory that contains application data for all users. A + /// typical path is C:\Documents and Settings\All Users\Application Data. This + /// folder is used for application data that is not user specific. For + /// example, an application can store a spell-check dictionary, a database of + /// clip art, or a log file in the CSIDL_COMMON_APPDATA folder. This + /// information will not roam and is available to anyone using the computer. + static String get ProgramData => '{62AB5D82-FDC1-4DC3-A9DD-070D1D495D97}'; + + /// The Program Files folder. A typical path is C:\Program Files. + static String get ProgramFiles => '{905e63b6-c1bf-494e-b29c-65b732d3d21a}'; + + /// The common Program Files folder. A typical path is C:\Program + /// Files\Common. + static String get ProgramFilesCommon => + '{F7F1ED05-9F6D-47A2-AAAE-29D317C6F066}'; + + /// On 64-bit systems, a link to the common Program Files folder. A typical path is + /// C:\Program Files\Common Files. + static String get ProgramFilesCommonX64 => + '{6365D5A7-0F0D-45e5-87F6-0DA56B6A4F7D}'; + + /// On 64-bit systems, a link to the 32-bit common Program Files folder. A + /// typical path is C:\Program Files (x86)\Common Files. On 32-bit systems, a + /// link to the Common Program Files folder. + static String get ProgramFilesCommonX86 => + '{DE974D24-D9C6-4D3E-BF91-F4455120B917}'; + + /// On 64-bit systems, a link to the Program Files folder. A typical path is + /// C:\Program Files. + static String get ProgramFilesX64 => '{6D809377-6AF0-444b-8957-A3773F02200E}'; + + /// On 64-bit systems, a link to the 32-bit Program Files folder. A typical + /// path is C:\Program Files (x86). On 32-bit systems, a link to the Common + /// Program Files folder. + static String get ProgramFilesX86 => '{7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E}'; + + /// The file system directory that contains the user's program groups (which + /// are themselves file system directories). + static String get Programs => '{A77F5D77-2E2B-44C3-A6A2-ABA601054A51}'; + + /// The file system directory that contains files and folders that appear on + /// the desktop for all users. A typical path is C:\Documents and Settings\All + /// Users\Desktop. + static String get PublicDesktop => '{C4AA340D-F20F-4863-AFEF-F87EF2E6BA25}'; + + /// The file system directory that contains documents that are common to all + /// users. A typical path is C:\Documents and Settings\All Users\Documents. + static String get PublicDocuments => '{ED4824AF-DCE4-45A8-81E2-FC7965083634}'; + + /// The file system directory that serves as a repository for music files + /// common to all users. A typical path is C:\Documents and Settings\All + /// Users\Documents\My Music. + static String get PublicMusic => '{3214FAB5-9757-4298-BB61-92A9DEAA44FF}'; + + /// The file system directory that serves as a repository for image files + /// common to all users. A typical path is C:\Documents and Settings\All + /// Users\Documents\My Pictures. + static String get PublicPictures => '{B6EBFB86-6907-413C-9AF7-4FC2ABF07CC5}'; + + /// The file system directory that serves as a repository for video files + /// common to all users. A typical path is C:\Documents and Settings\All + /// Users\Documents\My Videos. + static String get PublicVideos => '{2400183A-6185-49FB-A2D8-4A392A602BA3}'; + + /// The file system directory that contains shortcuts to the user's most + /// recently used documents. A typical path is C:\Documents and + /// Settings\username\My Recent Documents. + static String get Recent => '{AE50C081-EBD2-438A-8655-8A092E34987A}'; + + /// The virtual folder that contains the objects in the user's Recycle Bin. + static String get RecycleBinFolder => + '{B7534046-3ECB-4C18-BE4E-64CD4CB7D6AC}'; + + /// The file system directory that contains resource data. A typical path is + /// C:\Windows\Resources. + static String get ResourceDir => '{8AD10C31-2ADB-4296-A8F7-E4701232C972}'; + + /// The file system directory that serves as a common repository for + /// application-specific data. A typical path is C:\Documents and + /// Settings\username\Application Data. + static String get RoamingAppData => '{3EB685DB-65F9-4CF6-A03A-E3EF65729F3D}'; + + /// The file system directory that contains Send To menu items. A typical path + /// is C:\Documents and Settings\username\SendTo. + static String get SendTo => '{8983036C-27C0-404B-8F08-102D10DCFD74}'; + + /// The file system directory that contains Start menu items. A typical path + /// is C:\Documents and Settings\username\Start Menu. + static String get StartMenu => '{625B53C3-AB48-4EC1-BA1F-A1EF4146FC19}'; + + /// The file system directory that corresponds to the user's Startup program + /// group. The system starts these programs whenever the associated user logs + /// on. A typical path is C:\Documents and Settings\username\Start + /// Menu\Programs\Startup. + static String get Startup => '{B97D20BB-F46A-4C97-BA10-5E3608430854}'; + + /// The Windows System folder. A typical path is C:\Windows\System32. + static String get System => '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}'; + + /// The 32-bit Windows System folder. On 32-bit systems, this is typically + /// C:\Windows\system32. On 64-bit systems, this is typically + /// C:\Windows\syswow64. + static String get SystemX86 => '{D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27}'; + + /// The file system directory that serves as a common repository for document + /// templates. A typical path is C:\Documents and Settings\username\Templates. + static String get Templates => '{A63293E8-664E-48DB-A079-DF759E0509F7}'; + + /// The file system directory that serves as a common repository for video + /// files. A typical path is C:\Documents and Settings\username\My + /// Documents\My Videos. + static String get Videos => '{18989B1D-99B5-455B-841C-AB7C74E4DDFC}'; + + /// The Windows directory or SYSROOT. This corresponds to the %windir% or + /// %SYSTEMROOT% environment variables. A typical path is C:\Windows. + static String get Windows => '{F38BF404-1D43-42F2-9305-67DE0B28FC23}'; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/folders_stub.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/folders_stub.dart new file mode 100755 index 00000000..34e9e611 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/folders_stub.dart @@ -0,0 +1,6 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Stub version of the actual class. +class WindowsKnownFolder {} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/guid.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/guid.dart new file mode 100755 index 00000000..84daffe6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/guid.dart @@ -0,0 +1,51 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ffi'; +import 'dart:typed_data'; + +/// Representation of the Win32 GUID struct. +// For the layout of this struct, see +// https://learn.microsoft.com/windows/win32/api/guiddef/ns-guiddef-guid +@Packed(4) +base class GUID extends Struct { + /// Native Data1 field. + @Uint32() + external int data1; + + /// Native Data2 field. + @Uint16() + external int data2; + + /// Native Data3 field. + @Uint16() + external int data3; + + /// Native Data4 field. + // This should be an eight-element byte array, but there's no such annotation. + @Uint64() + external int data4; + + /// Parses a GUID string, with optional enclosing "{}"s and optional "-"s, + /// into data. + void parse(String guid) { + final String hexOnly = guid.replaceAll(RegExp(r'[{}-]'), ''); + if (hexOnly.length != 32) { + throw ArgumentError.value(guid, 'guid', 'Invalid GUID string'); + } + final ByteData bytes = ByteData(16); + for (int i = 0; i < 16; ++i) { + bytes.setUint8( + i, int.parse(hexOnly.substring(i * 2, i * 2 + 2), radix: 16)); + } + data1 = bytes.getInt32(0); + data2 = bytes.getInt16(4); + data3 = bytes.getInt16(6); + // [bytes] is big endian, but the host is little endian, so a default + // big-endian read would reverse the bytes. Since data4 is supposed to be + // a byte array, the order should be preserved, so do a little-endian read. + // https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding + data4 = bytes.getInt64(8, Endian.little); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/path_provider_windows_real.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/path_provider_windows_real.dart new file mode 100755 index 00000000..50f010ba --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/path_provider_windows_real.dart @@ -0,0 +1,280 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ffi'; +import 'dart:io'; + +import 'package:ffi/ffi.dart'; +import 'package:flutter/foundation.dart' show visibleForTesting; +import 'package:flutter/services.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; + +import 'folders.dart'; +import 'guid.dart'; +import 'win32_wrappers.dart'; + +/// Constant for en-US language used in VersionInfo keys. +@visibleForTesting +const String languageEn = '0409'; + +/// Constant for CP1252 encoding used in VersionInfo keys +@visibleForTesting +const String encodingCP1252 = '04e4'; + +/// Constant for Unicode encoding used in VersionInfo keys +@visibleForTesting +const String encodingUnicode = '04b0'; + +/// Wraps the Win32 VerQueryValue API call. +/// +/// This class exists to allow injecting alternate metadata in tests without +/// building multiple custom test binaries. +@visibleForTesting +class VersionInfoQuerier { + /// Returns the value for [key] in [versionInfo]s in section with given + /// language and encoding, or null if there is no such entry, + /// or if versionInfo is null. + /// + /// See https://docs.microsoft.com/windows/win32/menurc/versioninfo-resource + /// for list of possible language and encoding values. + String? getStringValue( + Pointer? versionInfo, + String key, { + required String language, + required String encoding, + }) { + assert(language.isNotEmpty); + assert(encoding.isNotEmpty); + if (versionInfo == null) { + return null; + } + final Pointer keyPath = + '\\StringFileInfo\\$language$encoding\\$key'.toNativeUtf16(); + final Pointer length = calloc(); + final Pointer> valueAddress = calloc>(); + try { + if (VerQueryValue(versionInfo, keyPath, valueAddress, length) == 0) { + return null; + } + return valueAddress.value.toDartString(); + } finally { + calloc.free(keyPath); + calloc.free(length); + calloc.free(valueAddress); + } + } +} + +/// The Windows implementation of [PathProviderPlatform] +/// +/// This class implements the `package:path_provider` functionality for Windows. +class PathProviderWindows extends PathProviderPlatform { + /// Registers the Windows implementation. + static void registerWith() { + PathProviderPlatform.instance = PathProviderWindows(); + } + + /// The object to use for performing VerQueryValue calls. + @visibleForTesting + VersionInfoQuerier versionInfoQuerier = VersionInfoQuerier(); + + /// This is typically the same as the TMP environment variable. + @override + Future getTemporaryPath() async { + final Pointer buffer = calloc(MAX_PATH + 1).cast(); + String path; + + try { + final int length = GetTempPath(MAX_PATH, buffer); + + if (length == 0) { + final int error = GetLastError(); + throw _createWin32Exception(error); + } else { + path = buffer.toDartString(); + + // GetTempPath adds a trailing backslash, but SHGetKnownFolderPath does + // not. Strip off trailing backslash for consistency with other methods + // here. + if (path.endsWith(r'\')) { + path = path.substring(0, path.length - 1); + } + } + + // Ensure that the directory exists, since GetTempPath doesn't. + final Directory directory = Directory(path); + if (!directory.existsSync()) { + await directory.create(recursive: true); + } + + return path; + } finally { + calloc.free(buffer); + } + } + + @override + Future getApplicationSupportPath() => + _createApplicationSubdirectory(WindowsKnownFolder.RoamingAppData); + + @override + Future getApplicationDocumentsPath() => + getPath(WindowsKnownFolder.Documents); + + @override + Future getApplicationCachePath() => + _createApplicationSubdirectory(WindowsKnownFolder.LocalAppData); + + @override + Future getDownloadsPath() => getPath(WindowsKnownFolder.Downloads); + + /// Retrieve any known folder from Windows. + /// + /// folderID is a GUID that represents a specific known folder ID, drawn from + /// [WindowsKnownFolder]. + Future getPath(String folderID) { + final Pointer> pathPtrPtr = calloc>(); + final Pointer knownFolderID = calloc()..ref.parse(folderID); + + try { + final int hr = SHGetKnownFolderPath( + knownFolderID, + KF_FLAG_DEFAULT, + NULL, + pathPtrPtr, + ); + + if (FAILED(hr)) { + if (hr == E_INVALIDARG || hr == E_FAIL) { + throw _createWin32Exception(hr); + } + return Future.value(); + } + + final String path = pathPtrPtr.value.toDartString(); + return Future.value(path); + } finally { + calloc.free(pathPtrPtr); + calloc.free(knownFolderID); + } + } + + String? _getStringValue(Pointer? infoBuffer, String key) => + versionInfoQuerier.getStringValue(infoBuffer, key, + language: languageEn, encoding: encodingCP1252) ?? + versionInfoQuerier.getStringValue(infoBuffer, key, + language: languageEn, encoding: encodingUnicode); + + /// Returns the relative path string to append to the root directory returned + /// by Win32 APIs for application storage (such as RoamingAppDir) to get a + /// directory that is unique to the application. + /// + /// The convention is to use company-name\product-name\. This will use that if + /// possible, using the data in the VERSIONINFO resource, with the following + /// fallbacks: + /// - If the company name isn't there, that component will be dropped. + /// - If the product name isn't there, it will use the exe's filename (without + /// extension). + String _getApplicationSpecificSubdirectory() { + String? companyName; + String? productName; + + final Pointer moduleNameBuffer = + calloc(MAX_PATH + 1).cast(); + final Pointer unused = calloc(); + Pointer? infoBuffer; + try { + // Get the module name. + final int moduleNameLength = + GetModuleFileName(0, moduleNameBuffer, MAX_PATH); + if (moduleNameLength == 0) { + final int error = GetLastError(); + throw _createWin32Exception(error); + } + + // From that, load the VERSIONINFO resource + final int infoSize = GetFileVersionInfoSize(moduleNameBuffer, unused); + if (infoSize != 0) { + infoBuffer = calloc(infoSize); + if (GetFileVersionInfo(moduleNameBuffer, 0, infoSize, infoBuffer) == + 0) { + calloc.free(infoBuffer); + infoBuffer = null; + } + } + companyName = + _sanitizedDirectoryName(_getStringValue(infoBuffer, 'CompanyName')); + productName = + _sanitizedDirectoryName(_getStringValue(infoBuffer, 'ProductName')); + + // If there was no product name, use the executable name. + productName ??= + path.basenameWithoutExtension(moduleNameBuffer.toDartString()); + + return companyName != null + ? path.join(companyName, productName) + : productName; + } finally { + calloc.free(moduleNameBuffer); + calloc.free(unused); + if (infoBuffer != null) { + calloc.free(infoBuffer); + } + } + } + + /// Makes [rawString] safe as a directory component. See + /// https://docs.microsoft.com/windows/win32/fileio/naming-a-file#naming-conventions + /// + /// If after sanitizing the string is empty, returns null. + String? _sanitizedDirectoryName(String? rawString) { + if (rawString == null) { + return null; + } + String sanitized = rawString + // Replace banned characters. + .replaceAll(RegExp(r'[<>:"/\\|?*]'), '_') + // Remove trailing whitespace. + .trimRight() + // Ensure that it does not end with a '.'. + .replaceAll(RegExp(r'[.]+$'), ''); + const int kMaxComponentLength = 255; + if (sanitized.length > kMaxComponentLength) { + sanitized = sanitized.substring(0, kMaxComponentLength); + } + return sanitized.isEmpty ? null : sanitized; + } + + Future _createApplicationSubdirectory(String folderId) async { + final String? baseDir = await getPath(folderId); + if (baseDir == null) { + return null; + } + final Directory directory = + Directory(path.join(baseDir, _getApplicationSpecificSubdirectory())); + // Ensure that the directory exists if possible, since it will on other + // platforms. If the name is longer than MAXPATH, creating will fail, so + // skip that step; it's up to the client to decide what to do with the path + // in that case (e.g., using a short path). + if (directory.path.length <= MAX_PATH) { + if (!directory.existsSync()) { + await directory.create(recursive: true); + } + } + return directory.path; + } +} + +Exception _createWin32Exception(int errorCode) { + return PlatformException( + code: 'Win32 Error', + // TODO(stuartmorgan): Consider getting the system error message via + // FormatMessage if it turns out to be necessary for debugging issues. + // Plugin-client-level usability isn't a major consideration since per + // https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#platform-exception-handling + // any case that comes up in practice should be handled and returned + // via a plugin-specific exception, not this fallback. + message: 'Error code 0x${errorCode.toRadixString(16)}'); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/path_provider_windows_stub.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/path_provider_windows_stub.dart new file mode 100755 index 00000000..bc851831 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/path_provider_windows_stub.dart @@ -0,0 +1,34 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; + +/// A stub implementation to satisfy compilation of multi-platform packages that +/// depend on path_provider_windows. This should never actually be created. +/// +/// Notably, because path_provider needs to manually register +/// path_provider_windows, anything with a transitive dependency on +/// path_provider will also depend on path_provider_windows, not just at the +/// pubspec level but the code level. +class PathProviderWindows extends PathProviderPlatform { + /// Errors on attempted instantiation of the stub. It exists only to satisfy + /// compile-time dependencies, and should never actually be created. + PathProviderWindows() : assert(false); + + /// Registers the Windows implementation. + static void registerWith() { + PathProviderPlatform.instance = PathProviderWindows(); + } + + /// Stub; see comment on VersionInfoQuerier. + VersionInfoQuerier versionInfoQuerier = VersionInfoQuerier(); + + /// Match PathProviderWindows so that the analyzer won't report invalid + /// overrides if tests provide fake PathProviderWindows implementations. + Future getPath(String folderID) async => ''; +} + +/// Stub to satisfy the analyzer, which doesn't seem to handle conditional +/// exports correctly. +class VersionInfoQuerier {} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/win32_wrappers.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/win32_wrappers.dart new file mode 100755 index 00000000..a39488eb --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/lib/src/win32_wrappers.dart @@ -0,0 +1,112 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// The types and functions here correspond directly to corresponding Windows +// types and functions, so the Windows docs are the definitive source of +// documentation. +// ignore_for_file: public_member_api_docs + +import 'dart:ffi'; + +import 'package:ffi/ffi.dart'; + +import 'guid.dart'; + +typedef BOOL = Int32; +typedef BYTE = Uint8; +typedef DWORD = Uint32; +typedef UINT = Uint32; +typedef HANDLE = IntPtr; +typedef HMODULE = HANDLE; +typedef HRESULT = Int32; +typedef LPCVOID = Pointer; +typedef LPCWSTR = Pointer; +typedef LPDWORD = Pointer; +typedef LPWSTR = Pointer; +typedef LPVOID = Pointer; +typedef PUINT = Pointer; +typedef PWSTR = Pointer>; +typedef WCHAR = Uint16; + +const int NULL = 0; + +// https://learn.microsoft.com/windows/win32/fileio/maximum-file-path-limitation?tabs=registry +const int MAX_PATH = 260; + +// https://learn.microsoft.com/windows/win32/seccrypto/common-hresult-values +// ignore: non_constant_identifier_names +final int E_FAIL = 0x80004005.toSigned(32); +// ignore: non_constant_identifier_names +final int E_INVALIDARG = 0x80070057.toSigned(32); + +// https://learn.microsoft.com/windows/win32/api/winerror/nf-winerror-failed#remarks +// ignore: non_constant_identifier_names +bool FAILED(int hr) => hr < 0; + +// https://learn.microsoft.com/windows/win32/api/shlobj_core/ne-shlobj_core-known_folder_flag +const int KF_FLAG_DEFAULT = 0x00000000; + +final DynamicLibrary _dllKernel32 = DynamicLibrary.open('kernel32.dll'); +final DynamicLibrary _dllVersion = DynamicLibrary.open('version.dll'); +final DynamicLibrary _dllShell32 = DynamicLibrary.open('shell32.dll'); + +// https://learn.microsoft.com/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath +typedef _FFITypeSHGetKnownFolderPath = HRESULT Function( + Pointer, DWORD, HANDLE, PWSTR); +typedef FFITypeSHGetKnownFolderPathDart = int Function( + Pointer, int, int, Pointer>); +// ignore: non_constant_identifier_names +final FFITypeSHGetKnownFolderPathDart SHGetKnownFolderPath = + _dllShell32.lookupFunction<_FFITypeSHGetKnownFolderPath, + FFITypeSHGetKnownFolderPathDart>('SHGetKnownFolderPath'); + +// https://learn.microsoft.com/windows/win32/api/winver/nf-winver-getfileversioninfow +typedef _FFITypeGetFileVersionInfoW = BOOL Function( + LPCWSTR, DWORD, DWORD, LPVOID); +typedef FFITypeGetFileVersionInfoW = int Function( + Pointer, int, int, Pointer); +// ignore: non_constant_identifier_names +final FFITypeGetFileVersionInfoW GetFileVersionInfo = _dllVersion + .lookupFunction<_FFITypeGetFileVersionInfoW, FFITypeGetFileVersionInfoW>( + 'GetFileVersionInfoW'); + +// https://learn.microsoft.com/windows/win32/api/winver/nf-winver-getfileversioninfosizew +typedef _FFITypeGetFileVersionInfoSizeW = DWORD Function(LPCWSTR, LPDWORD); +typedef FFITypeGetFileVersionInfoSizeW = int Function( + Pointer, Pointer); +// ignore: non_constant_identifier_names +final FFITypeGetFileVersionInfoSizeW GetFileVersionInfoSize = + _dllVersion.lookupFunction<_FFITypeGetFileVersionInfoSizeW, + FFITypeGetFileVersionInfoSizeW>('GetFileVersionInfoSizeW'); + +// https://learn.microsoft.com/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror +typedef _FFITypeGetLastError = DWORD Function(); +typedef FFITypeGetLastError = int Function(); +// ignore: non_constant_identifier_names +final FFITypeGetLastError GetLastError = _dllKernel32 + .lookupFunction<_FFITypeGetLastError, FFITypeGetLastError>('GetLastError'); + +// https://learn.microsoft.com/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulefilenamew +typedef _FFITypeGetModuleFileNameW = DWORD Function(HMODULE, LPWSTR, DWORD); +typedef FFITypeGetModuleFileNameW = int Function(int, Pointer, int); +// ignore: non_constant_identifier_names +final FFITypeGetModuleFileNameW GetModuleFileName = _dllKernel32.lookupFunction< + _FFITypeGetModuleFileNameW, + FFITypeGetModuleFileNameW>('GetModuleFileNameW'); + +// https://learn.microsoft.com/windows/win32/api/winver/nf-winver-verqueryvaluew +typedef _FFITypeVerQueryValueW = BOOL Function(LPCVOID, LPCWSTR, LPVOID, PUINT); +typedef FFITypeVerQueryValueW = int Function( + Pointer, Pointer, Pointer, Pointer); +// ignore: non_constant_identifier_names +final FFITypeVerQueryValueW VerQueryValue = + _dllVersion.lookupFunction<_FFITypeVerQueryValueW, FFITypeVerQueryValueW>( + 'VerQueryValueW'); + +// https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-gettemppathw +typedef _FFITypeGetTempPathW = DWORD Function(DWORD, LPWSTR); +typedef FFITypeGetTempPathW = int Function(int, Pointer); +// ignore: non_constant_identifier_names +final FFITypeGetTempPathW GetTempPath = _dllKernel32 + .lookupFunction<_FFITypeGetTempPathW, FFITypeGetTempPathW>('GetTempPathW'); diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/pubspec.yaml new file mode 100755 index 00000000..cb84e14a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/pubspec.yaml @@ -0,0 +1,32 @@ +name: path_provider_windows +description: Windows implementation of the path_provider plugin +repository: https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_windows +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+path_provider%22 +version: 2.3.0 + +environment: + sdk: ^3.2.0 + flutter: ">=3.16.0" + +flutter: + plugin: + implements: path_provider + platforms: + windows: + dartPluginClass: PathProviderWindows + +dependencies: + ffi: ^2.0.0 + flutter: + sdk: flutter + path: ^1.8.0 + path_provider_platform_interface: ^2.1.0 + +dev_dependencies: + flutter_test: + sdk: flutter + +topics: + - files + - path-provider + - paths diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/test/guid_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/test/guid_test.dart new file mode 100755 index 00000000..561ad3b8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/test/guid_test.dart @@ -0,0 +1,63 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ffi'; +import 'dart:typed_data'; + +import 'package:ffi/ffi.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path_provider_windows/src/guid.dart'; + +void main() { + test('has correct byte representation', () async { + final Pointer guid = calloc() + ..ref.parse('{00112233-4455-6677-8899-aabbccddeeff}'); + final ByteData data = ByteData(16) + ..setInt32(0, guid.ref.data1, Endian.little) + ..setInt16(4, guid.ref.data2, Endian.little) + ..setInt16(6, guid.ref.data3, Endian.little) + ..setInt64(8, guid.ref.data4, Endian.little); + expect(data.getUint8(0), 0x33); + expect(data.getUint8(1), 0x22); + expect(data.getUint8(2), 0x11); + expect(data.getUint8(3), 0x00); + expect(data.getUint8(4), 0x55); + expect(data.getUint8(5), 0x44); + expect(data.getUint8(6), 0x77); + expect(data.getUint8(7), 0x66); + expect(data.getUint8(8), 0x88); + expect(data.getUint8(9), 0x99); + expect(data.getUint8(10), 0xAA); + expect(data.getUint8(11), 0xBB); + expect(data.getUint8(12), 0xCC); + expect(data.getUint8(13), 0xDD); + expect(data.getUint8(14), 0xEE); + expect(data.getUint8(15), 0xFF); + + calloc.free(guid); + }); + + test('handles alternate forms', () async { + final Pointer guid1 = calloc() + ..ref.parse('{00112233-4455-6677-8899-aabbccddeeff}'); + final Pointer guid2 = calloc() + ..ref.parse('00112233445566778899AABBCCDDEEFF'); + + expect(guid1.ref.data1, guid2.ref.data1); + expect(guid1.ref.data2, guid2.ref.data2); + expect(guid1.ref.data3, guid2.ref.data3); + expect(guid1.ref.data4, guid2.ref.data4); + + calloc.free(guid1); + calloc.free(guid2); + }); + + test('throws for bad data', () async { + final Pointer guid = calloc(); + + expect(() => guid.ref.parse('{00112233-4455-6677-88'), throwsArgumentError); + + calloc.free(guid); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/test/path_provider_windows_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/test/path_provider_windows_test.dart new file mode 100755 index 00000000..f60b70fb --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/path_provider_windows/test/path_provider_windows_test.dart @@ -0,0 +1,190 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:ffi'; +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:path_provider_platform_interface/path_provider_platform_interface.dart'; +import 'package:path_provider_windows/path_provider_windows.dart'; +import 'package:path_provider_windows/src/path_provider_windows_real.dart' + show encodingCP1252, encodingUnicode, languageEn; + +// A fake VersionInfoQuerier that just returns preset responses. +class FakeVersionInfoQuerier implements VersionInfoQuerier { + FakeVersionInfoQuerier( + this.responses, { + this.language = languageEn, + this.encoding = encodingUnicode, + }); + + final String language; + final String encoding; + final Map responses; + + // ignore: unreachable_from_main + String? getStringValue( + Pointer? versionInfo, + String key, { + required String language, + required String encoding, + }) { + if (language == this.language && encoding == this.encoding) { + return responses[key]; + } else { + return null; + } + } +} + +void main() { + test('registered instance', () { + PathProviderWindows.registerWith(); + expect(PathProviderPlatform.instance, isA()); + }); + + test('getTemporaryPath', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + expect(await pathProvider.getTemporaryPath(), contains(r'C:\')); + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with no version info', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = + FakeVersionInfoQuerier({}); + final String? path = await pathProvider.getApplicationSupportPath(); + expect(path, contains(r'C:\')); + expect(path, contains(r'AppData')); + // The last path component should be the executable name. + expect(path, endsWith(r'flutter_tester')); + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with full version info in CP1252', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': 'A Company', + 'ProductName': 'Amazing App', + }, encoding: encodingCP1252); + final String? path = await pathProvider.getApplicationSupportPath(); + expect(path, isNotNull); + if (path != null) { + expect(path, endsWith(r'AppData\Roaming\A Company\Amazing App')); + expect(Directory(path).existsSync(), isTrue); + } + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with full version info in Unicode', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': 'A Company', + 'ProductName': 'Amazing App', + }); + final String? path = await pathProvider.getApplicationSupportPath(); + expect(path, isNotNull); + if (path != null) { + expect(path, endsWith(r'AppData\Roaming\A Company\Amazing App')); + expect(Directory(path).existsSync(), isTrue); + } + }, skip: !Platform.isWindows); + + test( + 'getApplicationSupportPath with full version info in Unsupported Encoding', + () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': 'A Company', + 'ProductName': 'Amazing App', + }, language: '0000', encoding: '0000'); + final String? path = await pathProvider.getApplicationSupportPath(); + expect(path, contains(r'C:\')); + expect(path, contains(r'AppData')); + // The last path component should be the executable name. + expect(path, endsWith(r'flutter_tester')); + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with missing company', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'ProductName': 'Amazing App', + }); + final String? path = await pathProvider.getApplicationSupportPath(); + expect(path, isNotNull); + if (path != null) { + expect(path, endsWith(r'AppData\Roaming\Amazing App')); + expect(Directory(path).existsSync(), isTrue); + } + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with problematic values', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': r'A Company: Name.', + 'ProductName': r'A"/Terrible\|App?*Name', + }); + final String? path = await pathProvider.getApplicationSupportPath(); + expect(path, isNotNull); + if (path != null) { + expect( + path, + endsWith( + r'AppData\Roaming\A _Bad_ Company_ Name\A__Terrible__App__Name')); + expect(Directory(path).existsSync(), isTrue); + } + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with a completely invalid company', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': r'..', + 'ProductName': r'Amazing App', + }); + final String? path = await pathProvider.getApplicationSupportPath(); + expect(path, isNotNull); + if (path != null) { + expect(path, endsWith(r'AppData\Roaming\Amazing App')); + expect(Directory(path).existsSync(), isTrue); + } + }, skip: !Platform.isWindows); + + test('getApplicationSupportPath with very long app name', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + final String truncatedName = 'A' * 255; + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': 'A Company', + 'ProductName': truncatedName * 2, + }); + final String? path = await pathProvider.getApplicationSupportPath(); + expect(path, endsWith('\\$truncatedName')); + // The directory won't exist, since it's longer than MAXPATH, so don't check + // that here. + }, skip: !Platform.isWindows); + + test('getApplicationDocumentsPath', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + final String? path = await pathProvider.getApplicationDocumentsPath(); + expect(path, contains(r'C:\')); + expect(path, contains(r'Documents')); + }, skip: !Platform.isWindows); + + test('getApplicationCachePath', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + pathProvider.versionInfoQuerier = FakeVersionInfoQuerier({ + 'CompanyName': 'A Company', + 'ProductName': 'Amazing App', + }, encoding: encodingCP1252); + final String? path = await pathProvider.getApplicationCachePath(); + expect(path, isNotNull); + if (path != null) { + expect(path, endsWith(r'AppData\Local\A Company\Amazing App')); + expect(Directory(path).existsSync(), isTrue); + } + }, skip: !Platform.isWindows); + + test('getDownloadsPath', () async { + final PathProviderWindows pathProvider = PathProviderWindows(); + final String? path = await pathProvider.getDownloadsPath(); + expect(path, contains(r'C:\')); + expect(path, contains(r'Downloads')); + }, skip: !Platform.isWindows); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows deleted file mode 120000 index 455b7b7f..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/permission_handler_windows-0.2.1/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/AUTHORS b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/AUTHORS new file mode 100755 index 00000000..67dfd55e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/AUTHORS @@ -0,0 +1,9 @@ + +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Baseflow +Alexandre Zollinger Chohfi +Maurits van Beusekom diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/CHANGELOG.md new file mode 100755 index 00000000..91c2f504 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/CHANGELOG.md @@ -0,0 +1,24 @@ +## 0.2.1 + +* Updates the dependency on `permission_handler_platform_interface` to version 4.1.0 (SiriKit support is only available for iOS and macOS). + +## 0.2.0 + +* Implements the `Permission.calendarWriteOnly` and `Permission.calendarFullAccess` permissions. +* Bumps `permission_handler_platform_interface` to version `4.0.0`. + +## 0.1.3 + +* Adds the new Android 13 permission "BODY_SENSORS_BACKGROUND" to PermissionHandlerEnums.h. + +## 0.1.2 + +* Adds the new Android 13 permissions "SCHEDULE_EXACT_ALARM, READ_MEDIA_IMAGES, READ_MEDIA_VIDEO and READ_MEDIA_AUDIO" to permission_constants.h. + +## 0.1.1 + +* Adds the new Android 13 NEARBY_WIFI_DEVICES permission to permission_constants.h. + +## 0.1.0 + +* Adds an initial implementation of Windows support for the permission_handler plugin. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/LICENSE new file mode 100755 index 00000000..bd6192f2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Baseflow + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/README.md new file mode 100755 index 00000000..0eb8fb99 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/README.md @@ -0,0 +1,23 @@ +# permission_handler_windows + +[![pub package](https://img.shields.io/pub/v/permission_handler_windows.svg)](https://pub.dartlang.org/packages/permission_handler_windows) ![Build status](https://github.com/Baseflow/flutter-permission-handler/workflows/permission_handler_android/badge.svg?branch=master) [![style: flutter lints](https://img.shields.io/badge/style-flutter_lints-40c4ff.svg)](https://pub.dev/packages/flutter_lints) + +The official Windows implementation of the [permission_handler](https://pub.dev/packages/permission_handler) plugin by [Baseflow](https://baseflow.com). + +## Usage + +Starting from version 9.2.0 of the [permission_handler](https://pub.dev/packages/permission_handler) plugin this is the endorsed Windows implementation. This means it will automatically be added to your dependencies when you depend on `permission_handler: ^9.2.0` in your applications pubspec.yaml. + +More detailed instructions on using the API can be found in the [README.md](../permission_handler/README.md) of the [permission_handler](https://pub.dev/packages/permission_handler) package. + +## Issues + +Please file any issues, bugs or feature requests as an issue on our [GitHub](https://github.com/Baseflow/flutter-permission-handler/issues) page. Commercial support is available, you can contact us at . + +## Want to contribute + +If you would like to contribute to the plugin (e.g. by improving the documentation, solving a bug or adding a cool new feature), please carefully review our [contribution guide](../CONTRIBUTING.md) and send us your [pull request](https://github.com/Baseflow/flutter-permission-handler/pulls). + +## Author + +This permission_handler plugin for Flutter is developed by [Baseflow](https://baseflow.com). diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/README.md new file mode 100755 index 00000000..cca8fca6 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/README.md @@ -0,0 +1,16 @@ +# permission_handler_example + +Demonstrates how to use the permission_handler plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.io/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/lib/main.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/lib/main.dart new file mode 100755 index 00000000..58a4dc05 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/lib/main.dart @@ -0,0 +1,141 @@ +import 'package:baseflow_plugin_template/baseflow_plugin_template.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; + +void main() { + runApp(BaseflowPluginExample( + pluginName: 'Permission Handler', + githubURL: 'https://github.com/Baseflow/flutter-permission-handler', + pubDevURL: 'https://pub.dev/packages/permission_handler', + pages: [PermissionHandlerWidget.createPage()])); +} + +///Defines the main theme color +final MaterialColor themeMaterialColor = + BaseflowPluginExample.createMaterialColor( + const Color.fromRGBO(48, 49, 60, 1)); + +/// A Flutter application demonstrating the functionality of this plugin +class PermissionHandlerWidget extends StatefulWidget { + /// Create a page containing the functionality of this plugin + static ExamplePage createPage() { + return ExamplePage( + Icons.location_on, (context) => PermissionHandlerWidget()); + } + + @override + _PermissionHandlerWidgetState createState() => + _PermissionHandlerWidgetState(); +} + +class _PermissionHandlerWidgetState extends State { + @override + Widget build(BuildContext context) { + return Center( + child: ListView( + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photos && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts; + }) + .map((permission) => PermissionWidget(permission)) + .toList()), + ); + } +} + +/// Permission widget containing information about the passed [Permission] +class PermissionWidget extends StatefulWidget { + /// Constructs a [PermissionWidget] for the supplied [Permission] + const PermissionWidget(this._permission); + + final Permission _permission; + + @override + _PermissionState createState() => _PermissionState(_permission); +} + +class _PermissionState extends State { + _PermissionState(this._permission); + + final Permission _permission; + final PermissionHandlerPlatform _permissionHandler = + PermissionHandlerPlatform.instance; + PermissionStatus _permissionStatus = PermissionStatus.denied; + + @override + void initState() { + super.initState(); + + _listenForPermissionStatus(); + } + + void _listenForPermissionStatus() async { + final status = await _permissionHandler.checkPermissionStatus(_permission); + setState(() => _permissionStatus = status); + } + + Color getPermissionColor() { + switch (_permissionStatus) { + case PermissionStatus.denied: + return Colors.red; + case PermissionStatus.granted: + return Colors.green; + case PermissionStatus.limited: + return Colors.orange; + default: + return Colors.grey; + } + } + + @override + Widget build(BuildContext context) { + return ListTile( + title: Text( + _permission.toString(), + style: Theme.of(context).textTheme.bodyLarge, + ), + subtitle: Text( + _permissionStatus.toString(), + style: TextStyle(color: getPermissionColor()), + ), + trailing: (_permission is PermissionWithService) + ? IconButton( + icon: const Icon( + Icons.info, + color: Colors.white, + ), + onPressed: () { + checkServiceStatus( + context, _permission as PermissionWithService); + }) + : null, + onTap: () { + requestPermission(_permission); + }, + ); + } + + void checkServiceStatus( + BuildContext context, PermissionWithService permission) async { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + (await _permissionHandler.checkServiceStatus(permission)).toString()), + )); + } + + Future requestPermission(Permission permission) async { + final status = await _permissionHandler.requestPermissions([permission]); + + setState(() { + print(status); + _permissionStatus = status[permission] ?? PermissionStatus.denied; + print(_permissionStatus); + }); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/pubspec.yaml new file mode 100755 index 00000000..2deb8e72 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/pubspec.yaml @@ -0,0 +1,33 @@ +name: permission_handler_windows_example +description: Demonstrates how to use the permission_handler_windows plugin. + +environment: + sdk: ">=2.15.0 <3.0.0" + +dependencies: + baseflow_plugin_template: ^2.1.1 + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + + permission_handler_windows: + # When depending on this package from a real application you should use: + # permission_handler_windows: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + url_launcher: ^6.0.12 + +flutter: + uses-material-design: true + + assets: + - res/images/baseflow_logo_def_light-02.png + - res/images/poweredByBaseflowLogoLight@3x.png + - packages/baseflow_plugin_template/logo.png + - packages/baseflow_plugin_template/poweredByBaseflow.png diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/baseflow_logo_def_light-02.png b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/baseflow_logo_def_light-02.png new file mode 100755 index 00000000..85f071f2 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/baseflow_logo_def_light-02.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/poweredByBaseflowLogoLight.png b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/poweredByBaseflowLogoLight.png new file mode 100755 index 00000000..6b9f1aae Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/poweredByBaseflowLogoLight.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/poweredByBaseflowLogoLight@2x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/poweredByBaseflowLogoLight@2x.png new file mode 100755 index 00000000..66901d9e Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/poweredByBaseflowLogoLight@2x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/poweredByBaseflowLogoLight@3x.png b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/poweredByBaseflowLogoLight@3x.png new file mode 100755 index 00000000..36fbdff3 Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/res/images/poweredByBaseflowLogoLight@3x.png differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/CMakeLists.txt new file mode 100755 index 00000000..1633297a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.14) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..b2e4bd8d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/generated_plugin_registrant.cc b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/generated_plugin_registrant.cc new file mode 100755 index 00000000..a0d0bbeb --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,17 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/generated_plugin_registrant.h b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/generated_plugin_registrant.h new file mode 100755 index 00000000..dc139d85 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/generated_plugins.cmake b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/generated_plugins.cmake new file mode 100755 index 00000000..c20a586d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,25 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + permission_handler_windows + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..de2d8916 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/Runner.rc b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/Runner.rc new file mode 100755 index 00000000..7a7335b8 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/flutter_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..3a11b51d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/flutter_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..28c23839 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/main.cpp new file mode 100755 index 00000000..ead0b228 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/resource.h b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/resource.h new file mode 100755 index 00000000..ddc7f3ef --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/resources/app_icon.ico b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/resources/app_icon.ico differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/runner.exe.manifest b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..2c680b8b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/utils.cpp new file mode 100755 index 00000000..05b53c01 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/utils.h new file mode 100755 index 00000000..3f0e05cb --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/win32_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..97f4439c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/win32_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/win32_window.h new file mode 100755 index 00000000..d9bcac1b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/example/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/pubspec.yaml new file mode 100755 index 00000000..f5553e0d --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/pubspec.yaml @@ -0,0 +1,25 @@ +name: permission_handler_windows +description: Permission plugin for Flutter. This plugin provides the Windows API to request and check permissions. +version: 0.2.1 +homepage: https://github.com/baseflow/flutter-permission-handler + +flutter: + plugin: + implements: permission_handler + platforms: + windows: + pluginClass: PermissionHandlerWindowsPlugin + +dependencies: + flutter: + sdk: flutter + permission_handler_platform_interface: ^4.1.0 + +dev_dependencies: + flutter_test: + sdk: flutter + plugin_platform_interface: ^2.0.0 + +environment: + sdk: ">=2.12.0 <4.0.0" + flutter: ">=2.0.0" diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/CMakeLists.txt new file mode 100755 index 00000000..79cf2ec2 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 3.15) +set(PROJECT_NAME "permission_handler_windows") +set(CPPWINRT_VERSION "2.0.210806.1") +project(${PROJECT_NAME} LANGUAGES CXX) +include(FetchContent) + +# This value is used when generating builds using this plugin, so it must +# not be changed +set(PLUGIN_NAME "${PROJECT_NAME}_plugin") + +FetchContent_Declare(nuget + URL "https://dist.nuget.org/win-x86-commandline/v6.0.0/nuget.exe" + URL_HASH SHA256=04eb6c4fe4213907e2773e1be1bbbd730e9a655a3c9c58387ce8d4a714a5b9e1 + DOWNLOAD_NO_EXTRACT true +) + +find_program(NUGET nuget) +if (NOT NUGET) + message("Nuget.exe not found, trying to download or use cached version.") + FetchContent_MakeAvailable(nuget) + set(NUGET ${nuget_SOURCE_DIR}/nuget.exe) +endif() + +execute_process(COMMAND + ${NUGET} install Microsoft.Windows.CppWinRT -Version ${CPPWINRT_VERSION} -OutputDirectory packages + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE ret) +if (NOT ret EQUAL 0) + message(FATAL_ERROR "Failed to install nuget package Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}") +endif() + +set(CPPWINRT ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}/bin/cppwinrt.exe) +execute_process(COMMAND + ${CPPWINRT} -input sdk -output include + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE ret) +if (NOT ret EQUAL 0) + message(FATAL_ERROR "Failed to run cppwinrt.exe") +endif() + +include_directories(BEFORE SYSTEM ${CMAKE_BINARY_DIR}/include) + +add_library(${PLUGIN_NAME} SHARED + "include/permission_handler_windows/permission_handler_windows_plugin.h" + "permission_handler_windows_plugin.cpp" +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) +target_compile_features(${PLUGIN_NAME} PRIVATE cxx_std_20) +target_compile_options(${PLUGIN_NAME} PRIVATE /await) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin) + +# List of absolute paths to libraries that should be bundled with the plugin +set(permission_handler_windows_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/include/permission_handler_windows/permission_handler_windows_plugin.h b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/include/permission_handler_windows/permission_handler_windows_plugin.h new file mode 100755 index 00000000..433198d9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/include/permission_handler_windows/permission_handler_windows_plugin.h @@ -0,0 +1,23 @@ +#ifndef PACKAGES_PERMISSION_HANDLER_PERMISSION_HANDLER_WINDOWS_WINDOWS_INCLUDE_PERMISSION_HANDLER_WINDOWS_PERMISSION_HANDLER_PLUGIN_H_ +#define PACKAGES_PERMISSION_HANDLER_PERMISSION_HANDLER_WINDOWS_WINDOWS_INCLUDE_PERMISSION_HANDLER_WINDOWS_PERMISSION_HANDLER_PLUGIN_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void PermissionHandlerWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // PACKAGES_PERMISSION_HANDLER_PERMISSION_HANDLER_WINDOWS_WINDOWS_INCLUDE_PERMISSION_HANDLER_WINDOWS_PERMISSION_HANDLER_PLUGIN_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/permission_constants.h b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/permission_constants.h new file mode 100755 index 00000000..3c3c4b07 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/permission_constants.h @@ -0,0 +1,70 @@ +#include + +class PermissionConstants { +public: + inline static int PERMISSION_CODE = 24; + inline static int PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS = 209; + inline static int PERMISSION_CODE_MANAGE_EXTERNAL_STORAGE = 210; + inline static int PERMISSION_CODE_SYSTEM_ALERT_WINDOW = 211; + inline static int PERMISSION_CODE_REQUEST_INSTALL_PACKAGES = 212; + inline static int PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY = 213; + + //PERMISSION_GROUP + enum class PermissionGroup { + CALENDAR = 0, + CAMERA = 1, + CONTACTS = 2, + LOCATION = 3, + LOCATION_ALWAYS = 4, + LOCATION_WHEN_IN_USE = 5, + MEDIA_LIBRARY = 6, + MICROPHONE = 7, + PHONE = 8, + PHOTOS = 9, + PHOTOS_ADD_ONLY = 10, + REMINDERS = 11, + SENSORS = 12, + SMS = 13, + SPEECH = 14, + STORAGE = 15, + IGNORE_BATTERY_OPTIMIZATIONS = 16, + NOTIFICATION = 17, + ACCESS_MEDIA_LOCATION = 18, + ACTIVITY_RECOGNITION = 19, + UNKNOWN = 20, + BLUETOOTH = 21, + MANAGE_EXTERNAL_STORAGE = 22, + SYSTEM_ALERT_WINDOW = 23, + REQUEST_INSTALL_PACKAGES = 24, + APP_TRACK_TRANSPARENCY = 25, + CRITICAL_ALERTS = 26, + ACCESS_NOTIFICATION_POLICY = 27, + BLUETOOTH_SCAN = 28, + BLUETOOTH_ADVERTISE = 29, + BLUETOOTH_CONNECT = 30, + NEARBY_WIFI_DEVICES = 31, + VIDEOS = 32, + AUDIO = 33, + SCHEDULE_EXACT_ALARM = 34, + SENSORS_ALWAYS = 35, + CALENDAR_WRITE_ONLY = 36, + CALENDAR_FULL_ACCESS = 37, + ASSISTANT = 38 + }; + + //PERMISSION_STATUS + enum class PermissionStatus { + DENIED = 0, + GRANTED = 1, + RESTRICTED = 2, + LIMITED = 3, + NEVER_ASK_AGAIN = 4 + }; + + //SERVICE_STATUS + enum class ServiceStatus { + DISABLED = 0, + ENABLED = 1, + NOT_APPLICABLE = 2 + }; +}; diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/permission_handler_windows_plugin.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/permission_handler_windows_plugin.cpp new file mode 100755 index 00000000..4b4d6d18 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/permission_handler_windows/windows/permission_handler_windows_plugin.cpp @@ -0,0 +1,193 @@ +#include "include/permission_handler_windows/permission_handler_windows_plugin.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "permission_constants.h" + +namespace { + +using namespace flutter; +using namespace winrt; +using namespace winrt::Windows::Devices::Geolocation; +using namespace winrt::Windows::Devices::Bluetooth; +using namespace winrt::Windows::Devices::Radios; + +template +T GetArgument(const std::string arg, const EncodableValue* args, T fallback) { + T result {fallback}; + const auto* arguments = std::get_if(args); + if (arguments) { + auto result_it = arguments->find(EncodableValue(arg)); + if (result_it != arguments->end()) { + result = std::get(result_it->second); + } + } + return result; +} + +class PermissionHandlerWindowsPlugin : public Plugin { + public: + static void RegisterWithRegistrar(PluginRegistrar* registrar); + + PermissionHandlerWindowsPlugin(); + + virtual ~PermissionHandlerWindowsPlugin(); + + // Disallow copy and move. + PermissionHandlerWindowsPlugin(const PermissionHandlerWindowsPlugin&) = delete; + PermissionHandlerWindowsPlugin& operator=(const PermissionHandlerWindowsPlugin&) = delete; + + // Called when a method is called on the plugin channel. + void HandleMethodCall(const MethodCall<>&, + std::unique_ptr>); + + private: + void IsLocationServiceEnabled(std::unique_ptr> result); + winrt::fire_and_forget IsBluetoothServiceEnabled(std::unique_ptr> result); + + winrt::Windows::Devices::Geolocation::Geolocator geolocator; + winrt::Windows::Devices::Geolocation::Geolocator::PositionChanged_revoker m_positionChangedRevoker; +}; + +// static +void PermissionHandlerWindowsPlugin::RegisterWithRegistrar( + PluginRegistrar* registrar) { + + auto channel = std::make_unique>( + registrar->messenger(), "flutter.baseflow.com/permissions/methods", + &StandardMethodCodec::GetInstance()); + + std::unique_ptr plugin = std::make_unique(); + + channel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto& call, auto result) { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); + + registrar->AddPlugin(std::move(plugin)); +} + +PermissionHandlerWindowsPlugin::PermissionHandlerWindowsPlugin(){ + m_positionChangedRevoker = geolocator.PositionChanged(winrt::auto_revoke, + [this](Geolocator const& geolocator, PositionChangedEventArgs e) + { + }); +} + +PermissionHandlerWindowsPlugin::~PermissionHandlerWindowsPlugin() = default; + +void PermissionHandlerWindowsPlugin::HandleMethodCall( + const MethodCall<>& method_call, + std::unique_ptr> result) { + + auto methodName = method_call.method_name(); + if (methodName.compare("checkServiceStatus") == 0) { + auto permission = (PermissionConstants::PermissionGroup)std::get(*method_call.arguments()); + if (permission == PermissionConstants::PermissionGroup::LOCATION || + permission == PermissionConstants::PermissionGroup::LOCATION_ALWAYS || + permission == PermissionConstants::PermissionGroup::LOCATION_WHEN_IN_USE) { + IsLocationServiceEnabled(std::move(result)); + return; + } + if(permission == PermissionConstants::PermissionGroup::BLUETOOTH){ + IsBluetoothServiceEnabled(std::move(result)); + return; + } + + if (permission == PermissionConstants::PermissionGroup::IGNORE_BATTERY_OPTIMIZATIONS) { + result->Success(EncodableValue((int)PermissionConstants::ServiceStatus::ENABLED)); + return; + } + + result->Success(EncodableValue((int)PermissionConstants::ServiceStatus::NOT_APPLICABLE)); + + } else if (methodName.compare("checkPermissionStatus") == 0) { + result->Success(EncodableValue((int)PermissionConstants::PermissionStatus::GRANTED)); + } else if (methodName.compare("requestPermissions") == 0) { + auto permissionsEncoded = std::get(*method_call.arguments()); + std::vector permissions; + permissions.reserve( permissionsEncoded.size() ); + std::transform( permissionsEncoded.begin(), permissionsEncoded.end(), + std::back_inserter( permissions ), + [](const EncodableValue& encoded) { + return std::get(encoded); + }); + + EncodableMap requestResults; + + for (int i=0;iSuccess(requestResults); + } else if (methodName.compare("shouldShowRequestPermissionRationale") == 0 + || methodName.compare("openAppSettings")) { + result->Success(EncodableValue(false)); + } else { + result->NotImplemented(); + } +} + +void PermissionHandlerWindowsPlugin::IsLocationServiceEnabled(std::unique_ptr> result) { + result->Success(EncodableValue((int)(geolocator.LocationStatus() != PositionStatus::NotAvailable + ? PermissionConstants::ServiceStatus::ENABLED + : PermissionConstants::ServiceStatus::DISABLED))); +} + +winrt::fire_and_forget PermissionHandlerWindowsPlugin::IsBluetoothServiceEnabled(std::unique_ptr> result) { + auto btAdapter = co_await BluetoothAdapter::GetDefaultAsync(); + + if (btAdapter == nullptr) { + result->Success(EncodableValue((int)PermissionConstants::ServiceStatus::DISABLED)); + co_return; + } + + if (!btAdapter.IsCentralRoleSupported()) { + result->Success(EncodableValue((int)PermissionConstants::ServiceStatus::DISABLED)); + co_return; + } + + auto radios = co_await Radio::GetRadiosAsync(); + + for (uint32_t i=0; iSuccess(EncodableValue((int)(radio.State() == RadioState::On + ? PermissionConstants::ServiceStatus::ENABLED + : PermissionConstants::ServiceStatus::DISABLED))); + co_return; + } + } + + result->Success(EncodableValue((int)PermissionConstants::ServiceStatus::DISABLED)); +} + +} // namespace + +void PermissionHandlerWindowsPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + PermissionHandlerWindowsPlugin::RegisterWithRegistrar( + PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows deleted file mode 120000 index 3b6b0b63..00000000 --- a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows +++ /dev/null @@ -1 +0,0 @@ -/home/pierre/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4/ \ No newline at end of file diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/AUTHORS b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/AUTHORS new file mode 100755 index 00000000..493a0b4e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/AUTHORS @@ -0,0 +1,66 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. +The Chromium Authors +German Saprykin +Benjamin Sauer +larsenthomasj@gmail.com +Ali Bitek +Pol Batlló +Anatoly Pulyaevskiy +Hayden Flinner +Stefano Rodriguez +Salvatore Giordano +Brian Armstrong +Paul DeMarco +Fabricio Nogueira +Simon Lightfoot +Ashton Thomas +Thomas Danner +Diego Velásquez +Hajime Nakamura +Tuyển Vũ Xuân +Miguel Ruivo +Sarthak Verma +Mike Diarmid +Invertase +Elliot Hesp +Vince Varga +Aawaz Gyawali +EUI Limited +Katarina Sheremet +Thomas Stockx +Sarbagya Dhaubanjar +Ozkan Eksi +Rishab Nayak +ko2ic +Jonathan Younger +Jose Sanchez +Debkanchan Samadder +Audrius Karosevicius +Lukasz Piliszczuk +SoundReply Solutions GmbH +Rafal Wachol +Pau Picas +Christian Weder +Alexandru Tuca +Christian Weder +Rhodes Davis Jr. +Luigi Agosti +Quentin Le Guennec +Koushik Ravikumar +Nissim Dsilva +Giancarlo Rocha +Ryo Miyake +Théo Champion +Kazuki Yamaguchi +Eitan Schwartz +Chris Rutkowski +Juan Alvarez +Aleksandr Yurkovskiy +Anton Borries +Alex Li +Rahul Raj <64.rahulraj@gmail.com> diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/CHANGELOG.md b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/CHANGELOG.md new file mode 100755 index 00000000..c5fafdf4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/CHANGELOG.md @@ -0,0 +1,114 @@ +## 3.1.4 + +* Updates minimum supported SDK version to Flutter 3.22/Dart 3.4. +* Fixes an issue where the URL logged would not be unescaped on failure. + +## 3.1.3 + +* Updates minimum supported SDK version to Flutter 3.19/Dart 3.3. +* Fixes handling of `file:` URLs that contain UTF-8 encoded paths. + +## 3.1.2 + +* Updates to pigeon 21. +* Updates minimum supported SDK version to Flutter 3.16/Dart 3.2. + +## 3.1.1 + +* Updates `launchUrl` to return false instead of throwing when there is no handler. +* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0. + +## 3.1.0 + +* Implements `supportsMode` and `supportsCloseForMode`. + +## 3.0.8 + +* Adds pub topics to package metadata. +* Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. + +## 3.0.7 + +* Updates pigeon dependency for url_launcher_windows to "^10.1.2". +* Updates minimum supported SDK version to Flutter 3.3/Dart 2.18. + +## 3.0.6 + +* Sets a cmake_policy compatibility version to fix build warnings. + +## 3.0.5 + +* Clarifies explanation of endorsement in README. +* Aligns Dart and Flutter SDK constraints. + +## 3.0.4 + +* Updates links for the merge of flutter/plugins into flutter/packages. + +## 3.0.3 + +* Converts internal implentation to Pigeon. +* Updates minimum Flutter version to 3.0. + +## 3.0.2 + +* Updates code for stricter lint checks. +* Updates minimum Flutter version to 2.10. + +## 3.0.1 + +* Fixes library_private_types_in_public_api, sort_child_properties_last and use_key_in_widget_constructors + lint warnings. + +## 3.0.0 + +* Changes the major version since, due to a typo in `default_package` in + existing versions of `url_launcher`, requiring Dart registration in this + package is in practice a breaking change. + * Does not include any API changes; clients can allow both 2.x or 3.x. + +## 2.0.3 + +**\[Retracted\]** + +* Switches to an in-package method channel implementation. +* Adds unit tests. +* Updates code for new analysis options. + +## 2.0.2 + +* Replaced reference to `shared_preferences` plugin with the `url_launcher` in the README. + +## 2.0.1 + +* Updated installation instructions in README. + +## 2.0.0 + +* Migrate to null-safety. +* Update the example app: remove the deprecated `RaisedButton` and `FlatButton` widgets. +* Set `implementation` in pubspec.yaml + +## 0.0.2+1 + +* Update Flutter SDK constraint. + +## 0.0.2 + +* Update integration test examples to use `testWidgets` instead of `test`. + +## 0.0.1+3 + +* Update Dart SDK constraint in example. + +## 0.0.1+2 + +* Check in windows/ directory for example/ + +## 0.0.1+1 + +* Update README to reflect endorsement. + +## 0.0.1 + +* Initial Windows implementation of `url_launcher`. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/LICENSE b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/LICENSE new file mode 100755 index 00000000..c6823b81 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/README.md new file mode 100755 index 00000000..cc31e7e7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/README.md @@ -0,0 +1,15 @@ +# url\_launcher\_windows + +The Windows implementation of [`url_launcher`][1]. + +## Usage + +This package is [endorsed][2], which means you can simply use `url_launcher` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. + +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. + +[1]: https://pub.dev/packages/url_launcher +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/README.md b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/README.md new file mode 100755 index 00000000..96b8bb17 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/integration_test/url_launcher_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/integration_test/url_launcher_test.dart new file mode 100755 index 00000000..c9d0d8c9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/integration_test/url_launcher_test.dart @@ -0,0 +1,20 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('canLaunch', (WidgetTester _) async { + final UrlLauncherPlatform launcher = UrlLauncherPlatform.instance; + + expect(await launcher.canLaunch('randomstring'), false); + + // Generally all devices should have some default browser. + expect(await launcher.canLaunch('http://flutter.dev'), true); + }); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/lib/main.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/lib/main.dart new file mode 100755 index 00000000..739d09d0 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/lib/main.dart @@ -0,0 +1,95 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: public_member_api_docs + +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'URL Launcher', + theme: ThemeData( + primarySwatch: Colors.blue, + ), + home: const MyHomePage(title: 'URL Launcher'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + Future? _launched; + + Future _launchInBrowser(String url) async { + if (await UrlLauncherPlatform.instance.canLaunch(url)) { + await UrlLauncherPlatform.instance.launch( + url, + useSafariVC: false, + useWebView: false, + enableJavaScript: false, + enableDomStorage: false, + universalLinksOnly: false, + headers: {}, + ); + } else { + throw Exception('Could not launch $url'); + } + } + + Widget _launchStatus(BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasError) { + return Text('Error: ${snapshot.error}'); + } else { + return const Text(''); + } + } + + @override + Widget build(BuildContext context) { + const String toLaunch = 'https://www.cylog.org/headers/'; + return Scaffold( + appBar: AppBar( + title: Text(widget.title), + ), + body: ListView( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Padding( + padding: EdgeInsets.all(16.0), + child: Text(toLaunch), + ), + ElevatedButton( + onPressed: () => setState(() { + _launched = _launchInBrowser(toLaunch); + }), + child: const Text('Launch in browser'), + ), + const Padding(padding: EdgeInsets.all(16.0)), + FutureBuilder(future: _launched, builder: _launchStatus), + ], + ), + ], + ), + ); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/pubspec.yaml new file mode 100755 index 00000000..f00c0ba7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/pubspec.yaml @@ -0,0 +1,28 @@ +name: url_launcher_example +description: Demonstrates the Windows implementation of the url_launcher plugin. +publish_to: none + +environment: + sdk: ^3.4.0 + flutter: ">=3.22.0" + +dependencies: + flutter: + sdk: flutter + url_launcher_platform_interface: ^2.2.0 + url_launcher_windows: + # When depending on this package from a real application you should use: + # url_launcher_windows: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + +flutter: + uses-material-design: true diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/test_driver/integration_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/test_driver/integration_test.dart new file mode 100755 index 00000000..4f10f2a5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/CMakeLists.txt new file mode 100755 index 00000000..5a5d2e80 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/CMakeLists.txt @@ -0,0 +1,100 @@ +cmake_minimum_required(VERSION 3.15) +project(example LANGUAGES CXX) + +set(BINARY_NAME "example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Enable the test target. +set(include_url_launcher_windows_tests TRUE) +# Provide an alias for the test target using the name expected by repo tooling. +add_custom_target(unit_tests DEPENDS url_launcher_windows_test) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/flutter/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/flutter/CMakeLists.txt new file mode 100755 index 00000000..0a917772 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,107 @@ +cmake_minimum_required(VERSION 3.15) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/flutter/generated_plugins.cmake b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/flutter/generated_plugins.cmake new file mode 100755 index 00000000..88b22e5c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/CMakeLists.txt new file mode 100755 index 00000000..977e38b5 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "run_loop.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/Runner.rc b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/Runner.rc new file mode 100755 index 00000000..41d1b5cf --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2020 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "example.exe" "\0" + VALUE "ProductName", "example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/flutter_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/flutter_window.cpp new file mode 100755 index 00000000..8e415602 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/flutter_window.cpp @@ -0,0 +1,68 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(RunLoop* run_loop, + const flutter::DartProject& project) + : run_loop_(run_loop), project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opporutunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/flutter_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/flutter_window.h new file mode 100755 index 00000000..8e9c12bb --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/flutter_window.h @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "run_loop.h" +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow driven by the |run_loop|, hosting a + // Flutter view running |project|. + explicit FlutterWindow(RunLoop* run_loop, + const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The run loop driving events for this window. + RunLoop* run_loop_; + + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/main.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/main.cpp new file mode 100755 index 00000000..c7dbde1c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/main.cpp @@ -0,0 +1,40 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "flutter_window.h" +#include "run_loop.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t* command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + RunLoop run_loop; + + flutter::DartProject project(L"data"); + FlutterWindow window(&run_loop, project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + run_loop.Run(); + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/resource.h b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/resource.h new file mode 100755 index 00000000..d5d958dc --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/resources/app_icon.ico b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/resources/app_icon.ico new file mode 100755 index 00000000..c04e20ca Binary files /dev/null and b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/resources/app_icon.ico differ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/run_loop.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/run_loop.cpp new file mode 100755 index 00000000..1916500e --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/run_loop.cpp @@ -0,0 +1,70 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "run_loop.h" + +#include + +#include + +RunLoop::RunLoop() {} + +RunLoop::~RunLoop() {} + +void RunLoop::Run() { + bool keep_running = true; + TimePoint next_flutter_event_time = TimePoint::clock::now(); + while (keep_running) { + std::chrono::nanoseconds wait_duration = + std::max(std::chrono::nanoseconds(0), + next_flutter_event_time - TimePoint::clock::now()); + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), + QS_ALLINPUT); + bool processed_events = false; + MSG message; + // All pending Windows messages must be processed; MsgWaitForMultipleObjects + // won't return again for items left in the queue after PeekMessage. + while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { + processed_events = true; + if (message.message == WM_QUIT) { + keep_running = false; + break; + } + ::TranslateMessage(&message); + ::DispatchMessage(&message); + // Allow Flutter to process messages each time a Windows message is + // processed, to prevent starvation. + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + // If the PeekMessage loop didn't run, process Flutter messages. + if (!processed_events) { + next_flutter_event_time = + std::min(next_flutter_event_time, ProcessFlutterMessages()); + } + } +} + +void RunLoop::RegisterFlutterInstance( + flutter::FlutterEngine* flutter_instance) { + flutter_instances_.insert(flutter_instance); +} + +void RunLoop::UnregisterFlutterInstance( + flutter::FlutterEngine* flutter_instance) { + flutter_instances_.erase(flutter_instance); +} + +RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { + TimePoint next_event_time = TimePoint::max(); + for (auto instance : flutter_instances_) { + std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); + if (wait_duration != std::chrono::nanoseconds::max()) { + next_event_time = + std::min(next_event_time, TimePoint::clock::now() + wait_duration); + } + } + return next_event_time; +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/run_loop.h b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/run_loop.h new file mode 100755 index 00000000..819ed3ed --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/run_loop.h @@ -0,0 +1,42 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_RUN_LOOP_H_ +#define RUNNER_RUN_LOOP_H_ + +#include + +#include +#include + +// A runloop that will service events for Flutter instances as well +// as native messages. +class RunLoop { + public: + RunLoop(); + ~RunLoop(); + + // Prevent copying + RunLoop(RunLoop const&) = delete; + RunLoop& operator=(RunLoop const&) = delete; + + // Runs the run loop until the application quits. + void Run(); + + // Registers the given Flutter instance for event servicing. + void RegisterFlutterInstance(flutter::FlutterEngine* flutter_instance); + + // Unregisters the given Flutter instance from event servicing. + void UnregisterFlutterInstance(flutter::FlutterEngine* flutter_instance); + + private: + using TimePoint = std::chrono::steady_clock::time_point; + + // Processes all currently pending messages for registered Flutter instances. + TimePoint ProcessFlutterMessages(); + + std::set flutter_instances_; +}; + +#endif // RUNNER_RUN_LOOP_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/runner.exe.manifest b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/runner.exe.manifest new file mode 100755 index 00000000..c977c4a4 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/utils.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/utils.cpp new file mode 100755 index 00000000..e875ce8b --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/utils.cpp @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE* unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/utils.h b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/utils.h new file mode 100755 index 00000000..16b3f079 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/utils.h @@ -0,0 +1,12 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +#endif // RUNNER_UTILS_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/win32_window.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/win32_window.cpp new file mode 100755 index 00000000..a609a200 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/win32_window.cpp @@ -0,0 +1,240 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/win32_window.h b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/win32_window.h new file mode 100755 index 00000000..d2a73005 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/example/windows/runner/win32_window.h @@ -0,0 +1,99 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/lib/url_launcher_windows.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/lib/url_launcher_windows.dart new file mode 100755 index 00000000..8ba77dc3 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/lib/url_launcher_windows.dart @@ -0,0 +1,58 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/foundation.dart'; +import 'package:url_launcher_platform_interface/link.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; + +import 'src/messages.g.dart'; + +/// An implementation of [UrlLauncherPlatform] for Windows. +class UrlLauncherWindows extends UrlLauncherPlatform { + /// Creates a new plugin implementation instance. + UrlLauncherWindows({ + @visibleForTesting UrlLauncherApi? api, + }) : _hostApi = api ?? UrlLauncherApi(); + + final UrlLauncherApi _hostApi; + + /// Registers this class as the default instance of [UrlLauncherPlatform]. + static void registerWith() { + UrlLauncherPlatform.instance = UrlLauncherWindows(); + } + + @override + final LinkDelegate? linkDelegate = null; + + @override + Future canLaunch(String url) { + return _hostApi.canLaunchUrl(url); + } + + @override + Future launch( + String url, { + required bool useSafariVC, + required bool useWebView, + required bool enableJavaScript, + required bool enableDomStorage, + required bool universalLinksOnly, + required Map headers, + String? webOnlyWindowName, + }) async { + return _hostApi.launchUrl(url); + } + + @override + Future supportsMode(PreferredLaunchMode mode) async { + return mode == PreferredLaunchMode.platformDefault || + mode == PreferredLaunchMode.externalApplication; + } + + @override + Future supportsCloseForMode(PreferredLaunchMode mode) async { + // No supported mode is closeable. + return false; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/pigeons/copyright.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/pigeons/copyright.txt new file mode 100755 index 00000000..1236b63c --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/pigeons/messages.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/pigeons/messages.dart new file mode 100755 index 00000000..28152e45 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/pigeons/messages.dart @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon(PigeonOptions( + dartOut: 'lib/src/messages.g.dart', + cppOptions: CppOptions(namespace: 'url_launcher_windows'), + cppHeaderOut: 'windows/messages.g.h', + cppSourceOut: 'windows/messages.g.cpp', + copyrightHeader: 'pigeons/copyright.txt', +)) +@HostApi(dartHostTestHandler: 'TestUrlLauncherApi') +abstract class UrlLauncherApi { + bool canLaunchUrl(String url); + bool launchUrl(String url); +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/pubspec.yaml b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/pubspec.yaml new file mode 100755 index 00000000..51e3e46a --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/pubspec.yaml @@ -0,0 +1,34 @@ +name: url_launcher_windows +description: Windows implementation of the url_launcher plugin. +repository: https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_windows +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22 +version: 3.1.4 + +environment: + sdk: ^3.4.0 + flutter: ">=3.22.0" + +flutter: + plugin: + implements: url_launcher + platforms: + windows: + pluginClass: UrlLauncherWindows + dartPluginClass: UrlLauncherWindows + +dependencies: + flutter: + sdk: flutter + url_launcher_platform_interface: ^2.2.0 + +dev_dependencies: + flutter_test: + sdk: flutter + pigeon: ^21.0.0 + test: ^1.16.3 + +topics: + - links + - os-integration + - url-launcher + - urls diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/test/url_launcher_windows_test.dart b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/test/url_launcher_windows_test.dart new file mode 100755 index 00000000..5d8efc03 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/test/url_launcher_windows_test.dart @@ -0,0 +1,165 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart'; +import 'package:url_launcher_windows/src/messages.g.dart'; +import 'package:url_launcher_windows/url_launcher_windows.dart'; + +void main() { + late _FakeUrlLauncherApi api; + late UrlLauncherWindows plugin; + + setUp(() { + api = _FakeUrlLauncherApi(); + plugin = UrlLauncherWindows(api: api); + }); + + test('registers instance', () { + UrlLauncherWindows.registerWith(); + expect(UrlLauncherPlatform.instance, isA()); + }); + + group('canLaunch', () { + test('handles true', () async { + api.canLaunch = true; + + final bool result = await plugin.canLaunch('http://example.com/'); + + expect(result, isTrue); + expect(api.argument, 'http://example.com/'); + }); + + test('handles false', () async { + api.canLaunch = false; + + final bool result = await plugin.canLaunch('http://example.com/'); + + expect(result, isFalse); + expect(api.argument, 'http://example.com/'); + }); + }); + + group('launch', () { + test('handles success', () async { + api.canLaunch = true; + + expect( + await plugin.launch( + 'http://example.com/', + useSafariVC: true, + useWebView: false, + enableJavaScript: false, + enableDomStorage: false, + universalLinksOnly: false, + headers: const {}, + ), + true); + expect(api.argument, 'http://example.com/'); + }); + + test('handles failure', () async { + api.canLaunch = false; + + expect( + await plugin.launch( + 'http://example.com/', + useSafariVC: true, + useWebView: false, + enableJavaScript: false, + enableDomStorage: false, + universalLinksOnly: false, + headers: const {}, + ), + false); + expect(api.argument, 'http://example.com/'); + }); + + test('handles errors', () async { + api.throwError = true; + + await expectLater( + plugin.launch( + 'http://example.com/', + useSafariVC: true, + useWebView: false, + enableJavaScript: false, + enableDomStorage: false, + universalLinksOnly: false, + headers: const {}, + ), + throwsA(isA())); + expect(api.argument, 'http://example.com/'); + }); + }); + + group('supportsMode', () { + test('returns true for platformDefault', () async { + final UrlLauncherWindows launcher = UrlLauncherWindows(api: api); + expect(await launcher.supportsMode(PreferredLaunchMode.platformDefault), + true); + }); + + test('returns true for external application', () async { + final UrlLauncherWindows launcher = UrlLauncherWindows(api: api); + expect( + await launcher.supportsMode(PreferredLaunchMode.externalApplication), + true); + }); + + test('returns false for other modes', () async { + final UrlLauncherWindows launcher = UrlLauncherWindows(api: api); + expect( + await launcher + .supportsMode(PreferredLaunchMode.externalNonBrowserApplication), + false); + expect(await launcher.supportsMode(PreferredLaunchMode.inAppBrowserView), + false); + expect( + await launcher.supportsMode(PreferredLaunchMode.inAppWebView), false); + }); + }); + + test('supportsCloseForMode returns false', () async { + final UrlLauncherWindows launcher = UrlLauncherWindows(api: api); + expect( + await launcher + .supportsCloseForMode(PreferredLaunchMode.platformDefault), + false); + expect( + await launcher + .supportsCloseForMode(PreferredLaunchMode.externalApplication), + false); + }); +} + +class _FakeUrlLauncherApi implements UrlLauncherApi { + /// The argument that was passed to an API call. + String? argument; + + /// Controls the behavior of the fake canLaunch implementations. + /// + /// - [canLaunchUrl] returns this value. + /// - [launchUrl] returns this value if [throwError] is false. + bool canLaunch = false; + + /// Whether to throw a platform exception. + bool throwError = false; + + @override + Future canLaunchUrl(String url) async { + argument = url; + return canLaunch; + } + + @override + Future launchUrl(String url) async { + argument = url; + if (throwError) { + throw PlatformException(code: 'Failed'); + } + return canLaunch; + } +} diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/CMakeLists.txt b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/CMakeLists.txt new file mode 100755 index 00000000..2b07f3a7 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.10) +set(PROJECT_NAME "url_launcher_windows") +project(${PROJECT_NAME} LANGUAGES CXX) + +cmake_policy(VERSION 3.10...3.24) + +set(PLUGIN_NAME "${PROJECT_NAME}_plugin") + +list(APPEND PLUGIN_SOURCES + "messages.g.cpp" + "messages.g.h" + "system_apis.cpp" + "system_apis.h" + "url_launcher_plugin.cpp" + "url_launcher_plugin.h" +) + +add_library(${PLUGIN_NAME} SHARED + "include/url_launcher_windows/url_launcher_windows.h" + "url_launcher_windows.cpp" + ${PLUGIN_SOURCES} +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin shlwapi.lib) + +# List of absolute paths to libraries that should be bundled with the plugin +set(file_chooser_bundled_libraries + "" + PARENT_SCOPE +) + + +# === Tests === + +if (${include_${PROJECT_NAME}_tests}) +set(TEST_RUNNER "${PROJECT_NAME}_test") +enable_testing() +# TODO(stuartmorgan): Consider using a single shared, pre-checked-in googletest +# instance rather than downloading for each plugin. This approach makes sense +# for a template, but not for a monorepo with many plugins. +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/release-1.11.0.zip +) +# Prevent overriding the parent project's compiler/linker settings +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) +# Disable install commands for gtest so it doesn't end up in the bundle. +set(INSTALL_GTEST OFF CACHE BOOL "Disable installation of googletest" FORCE) + +FetchContent_MakeAvailable(googletest) + +# The plugin's C API is not very useful for unit testing, so build the sources +# directly into the test binary rather than using the DLL. +add_executable(${TEST_RUNNER} + test/url_launcher_windows_test.cpp + ${PLUGIN_SOURCES} +) +apply_standard_settings(${TEST_RUNNER}) +target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") +target_link_libraries(${TEST_RUNNER} PRIVATE flutter_wrapper_plugin shlwapi.lib) +target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock) +# flutter_wrapper_plugin has link dependencies on the Flutter DLL. +add_custom_command(TARGET ${TEST_RUNNER} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${FLUTTER_LIBRARY}" $ +) + +include(GoogleTest) +gtest_discover_tests(${TEST_RUNNER}) +endif() diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/include/url_launcher_windows/url_launcher_windows.h b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/include/url_launcher_windows/url_launcher_windows.h new file mode 100755 index 00000000..251471c9 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/include/url_launcher_windows/url_launcher_windows.h @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#ifndef PACKAGES_URL_LAUNCHER_URL_LAUNCHER_WINDOWS_WINDOWS_INCLUDE_URL_LAUNCHER_WINDOWS_URL_LAUNCHER_PLUGIN_H_ +#define PACKAGES_URL_LAUNCHER_URL_LAUNCHER_WINDOWS_WINDOWS_INCLUDE_URL_LAUNCHER_WINDOWS_URL_LAUNCHER_PLUGIN_H_ + +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void UrlLauncherWindowsRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // PACKAGES_URL_LAUNCHER_URL_LAUNCHER_WINDOWS_WINDOWS_INCLUDE_URL_LAUNCHER_WINDOWS_URL_LAUNCHER_PLUGIN_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/messages.g.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/messages.g.cpp new file mode 100755 index 00000000..babca59f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/messages.g.cpp @@ -0,0 +1,148 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v21.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#undef _HAS_EXCEPTIONS + +#include "messages.g.h" + +#include +#include +#include +#include + +#include +#include +#include + +namespace url_launcher_windows { +using flutter::BasicMessageChannel; +using flutter::CustomEncodableValue; +using flutter::EncodableList; +using flutter::EncodableMap; +using flutter::EncodableValue; + +FlutterError CreateConnectionError(const std::string channel_name) { + return FlutterError( + "channel-error", + "Unable to establish connection on channel: '" + channel_name + "'.", + EncodableValue("")); +} + +PigeonCodecSerializer::PigeonCodecSerializer() {} + +EncodableValue PigeonCodecSerializer::ReadValueOfType( + uint8_t type, flutter::ByteStreamReader* stream) const { + return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); +} + +void PigeonCodecSerializer::WriteValue( + const EncodableValue& value, flutter::ByteStreamWriter* stream) const { + flutter::StandardCodecSerializer::WriteValue(value, stream); +} + +/// The codec used by UrlLauncherApi. +const flutter::StandardMessageCodec& UrlLauncherApi::GetCodec() { + return flutter::StandardMessageCodec::GetInstance( + &PigeonCodecSerializer::GetInstance()); +} + +// Sets up an instance of `UrlLauncherApi` to handle messages through the +// `binary_messenger`. +void UrlLauncherApi::SetUp(flutter::BinaryMessenger* binary_messenger, + UrlLauncherApi* api) { + UrlLauncherApi::SetUp(binary_messenger, api, ""); +} + +void UrlLauncherApi::SetUp(flutter::BinaryMessenger* binary_messenger, + UrlLauncherApi* api, + const std::string& message_channel_suffix) { + const std::string prepended_suffix = + message_channel_suffix.length() > 0 + ? std::string(".") + message_channel_suffix + : ""; + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.url_launcher_windows.UrlLauncherApi.canLaunchUrl" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_url_arg = args.at(0); + if (encodable_url_arg.IsNull()) { + reply(WrapError("url_arg unexpectedly null.")); + return; + } + const auto& url_arg = std::get(encodable_url_arg); + ErrorOr output = api->CanLaunchUrl(url_arg); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } + { + BasicMessageChannel<> channel( + binary_messenger, + "dev.flutter.pigeon.url_launcher_windows.UrlLauncherApi.launchUrl" + + prepended_suffix, + &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler( + [api](const EncodableValue& message, + const flutter::MessageReply& reply) { + try { + const auto& args = std::get(message); + const auto& encodable_url_arg = args.at(0); + if (encodable_url_arg.IsNull()) { + reply(WrapError("url_arg unexpectedly null.")); + return; + } + const auto& url_arg = std::get(encodable_url_arg); + ErrorOr output = api->LaunchUrl(url_arg); + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(EncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } +} + +EncodableValue UrlLauncherApi::WrapError(std::string_view error_message) { + return EncodableValue( + EncodableList{EncodableValue(std::string(error_message)), + EncodableValue("Error"), EncodableValue()}); +} + +EncodableValue UrlLauncherApi::WrapError(const FlutterError& error) { + return EncodableValue(EncodableList{EncodableValue(error.code()), + EncodableValue(error.message()), + error.details()}); +} + +} // namespace url_launcher_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/messages.g.h b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/messages.g.h new file mode 100755 index 00000000..c940969f --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/messages.g.h @@ -0,0 +1,103 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v21.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +#ifndef PIGEON_MESSAGES_G_H_ +#define PIGEON_MESSAGES_G_H_ +#include +#include +#include +#include + +#include +#include +#include + +namespace url_launcher_windows { + +// Generated class from Pigeon. + +class FlutterError { + public: + explicit FlutterError(const std::string& code) : code_(code) {} + explicit FlutterError(const std::string& code, const std::string& message) + : code_(code), message_(message) {} + explicit FlutterError(const std::string& code, const std::string& message, + const flutter::EncodableValue& details) + : code_(code), message_(message), details_(details) {} + + const std::string& code() const { return code_; } + const std::string& message() const { return message_; } + const flutter::EncodableValue& details() const { return details_; } + + private: + std::string code_; + std::string message_; + flutter::EncodableValue details_; +}; + +template +class ErrorOr { + public: + ErrorOr(const T& rhs) : v_(rhs) {} + ErrorOr(const T&& rhs) : v_(std::move(rhs)) {} + ErrorOr(const FlutterError& rhs) : v_(rhs) {} + ErrorOr(const FlutterError&& rhs) : v_(std::move(rhs)) {} + + bool has_error() const { return std::holds_alternative(v_); } + const T& value() const { return std::get(v_); }; + const FlutterError& error() const { return std::get(v_); }; + + private: + friend class UrlLauncherApi; + ErrorOr() = default; + T TakeValue() && { return std::get(std::move(v_)); } + + std::variant v_; +}; + +class PigeonCodecSerializer : public flutter::StandardCodecSerializer { + public: + PigeonCodecSerializer(); + inline static PigeonCodecSerializer& GetInstance() { + static PigeonCodecSerializer sInstance; + return sInstance; + } + + void WriteValue(const flutter::EncodableValue& value, + flutter::ByteStreamWriter* stream) const override; + + protected: + flutter::EncodableValue ReadValueOfType( + uint8_t type, flutter::ByteStreamReader* stream) const override; +}; + +// Generated interface from Pigeon that represents a handler of messages from +// Flutter. +class UrlLauncherApi { + public: + UrlLauncherApi(const UrlLauncherApi&) = delete; + UrlLauncherApi& operator=(const UrlLauncherApi&) = delete; + virtual ~UrlLauncherApi() {} + virtual ErrorOr CanLaunchUrl(const std::string& url) = 0; + virtual ErrorOr LaunchUrl(const std::string& url) = 0; + + // The codec used by UrlLauncherApi. + static const flutter::StandardMessageCodec& GetCodec(); + // Sets up an instance of `UrlLauncherApi` to handle messages through the + // `binary_messenger`. + static void SetUp(flutter::BinaryMessenger* binary_messenger, + UrlLauncherApi* api); + static void SetUp(flutter::BinaryMessenger* binary_messenger, + UrlLauncherApi* api, + const std::string& message_channel_suffix); + static flutter::EncodableValue WrapError(std::string_view error_message); + static flutter::EncodableValue WrapError(const FlutterError& error); + + protected: + UrlLauncherApi() = default; +}; +} // namespace url_launcher_windows +#endif // PIGEON_MESSAGES_G_H_ diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/system_apis.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/system_apis.cpp new file mode 100755 index 00000000..cde95ee1 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/system_apis.cpp @@ -0,0 +1,38 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "system_apis.h" + +#include + +namespace url_launcher_windows { + +SystemApis::SystemApis() {} + +SystemApis::~SystemApis() {} + +SystemApisImpl::SystemApisImpl() {} + +SystemApisImpl::~SystemApisImpl() {} + +LSTATUS SystemApisImpl::RegCloseKey(HKEY key) { return ::RegCloseKey(key); } + +LSTATUS SystemApisImpl::RegOpenKeyExW(HKEY key, LPCWSTR sub_key, DWORD options, + REGSAM desired, PHKEY result) { + return ::RegOpenKeyExW(key, sub_key, options, desired, result); +} + +LSTATUS SystemApisImpl::RegQueryValueExW(HKEY key, LPCWSTR value_name, + LPDWORD type, LPBYTE data, + LPDWORD data_size) { + return ::RegQueryValueExW(key, value_name, nullptr, type, data, data_size); +} + +HINSTANCE SystemApisImpl::ShellExecuteW(HWND hwnd, LPCWSTR operation, + LPCWSTR file, LPCWSTR parameters, + LPCWSTR directory, int show_flags) { + return ::ShellExecuteW(hwnd, operation, file, parameters, directory, + show_flags); +} + +} // namespace url_launcher_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/system_apis.h b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/system_apis.h new file mode 100755 index 00000000..c56c4100 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/system_apis.h @@ -0,0 +1,56 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include + +namespace url_launcher_windows { + +// An interface wrapping system APIs used by the plugin, for mocking. +class SystemApis { + public: + SystemApis(); + virtual ~SystemApis(); + + // Disallow copy and move. + SystemApis(const SystemApis&) = delete; + SystemApis& operator=(const SystemApis&) = delete; + + // Wrapper for RegCloseKey. + virtual LSTATUS RegCloseKey(HKEY key) = 0; + + // Wrapper for RegQueryValueEx. + virtual LSTATUS RegQueryValueExW(HKEY key, LPCWSTR value_name, LPDWORD type, + LPBYTE data, LPDWORD data_size) = 0; + + // Wrapper for RegOpenKeyEx. + virtual LSTATUS RegOpenKeyExW(HKEY key, LPCWSTR sub_key, DWORD options, + REGSAM desired, PHKEY result) = 0; + + // Wrapper for ShellExecute. + virtual HINSTANCE ShellExecuteW(HWND hwnd, LPCWSTR operation, LPCWSTR file, + LPCWSTR parameters, LPCWSTR directory, + int show_flags) = 0; +}; + +// Implementation of SystemApis using the Win32 APIs. +class SystemApisImpl : public SystemApis { + public: + SystemApisImpl(); + virtual ~SystemApisImpl(); + + // Disallow copy and move. + SystemApisImpl(const SystemApisImpl&) = delete; + SystemApisImpl& operator=(const SystemApisImpl&) = delete; + + // SystemApis Implementation: + virtual LSTATUS RegCloseKey(HKEY key); + virtual LSTATUS RegOpenKeyExW(HKEY key, LPCWSTR sub_key, DWORD options, + REGSAM desired, PHKEY result); + virtual LSTATUS RegQueryValueExW(HKEY key, LPCWSTR value_name, LPDWORD type, + LPBYTE data, LPDWORD data_size); + virtual HINSTANCE ShellExecuteW(HWND hwnd, LPCWSTR operation, LPCWSTR file, + LPCWSTR parameters, LPCWSTR directory, + int show_flags); +}; + +} // namespace url_launcher_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/test/url_launcher_windows_test.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/test/url_launcher_windows_test.cpp new file mode 100755 index 00000000..ac933e22 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/test/url_launcher_windows_test.cpp @@ -0,0 +1,188 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "messages.g.h" +#include "url_launcher_plugin.h" + +namespace url_launcher_windows { +namespace test { + +namespace { + +using flutter::EncodableMap; +using flutter::EncodableValue; +using ::testing::_; +using ::testing::DoAll; +using ::testing::HasSubstr; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SetArgPointee; +using ::testing::StrEq; + +class MockSystemApis : public SystemApis { + public: + MOCK_METHOD(LSTATUS, RegCloseKey, (HKEY key), (override)); + MOCK_METHOD(LSTATUS, RegQueryValueExW, + (HKEY key, LPCWSTR value_name, LPDWORD type, LPBYTE data, + LPDWORD data_size), + (override)); + MOCK_METHOD(LSTATUS, RegOpenKeyExW, + (HKEY key, LPCWSTR sub_key, DWORD options, REGSAM desired, + PHKEY result), + (override)); + MOCK_METHOD(HINSTANCE, ShellExecuteW, + (HWND hwnd, LPCWSTR operation, LPCWSTR file, LPCWSTR parameters, + LPCWSTR directory, int show_flags), + (override)); +}; + +} // namespace + +TEST(UrlLauncherPlugin, CanLaunchSuccessTrue) { + std::unique_ptr system = std::make_unique(); + + // Return success values from the registery commands. + HKEY fake_key = reinterpret_cast(1); + EXPECT_CALL(*system, RegOpenKeyExW) + .WillOnce(DoAll(SetArgPointee<4>(fake_key), Return(ERROR_SUCCESS))); + EXPECT_CALL(*system, RegQueryValueExW).WillOnce(Return(ERROR_SUCCESS)); + EXPECT_CALL(*system, RegCloseKey(fake_key)).WillOnce(Return(ERROR_SUCCESS)); + + UrlLauncherPlugin plugin(std::move(system)); + ErrorOr result = plugin.CanLaunchUrl("https://some.url.com"); + + ASSERT_FALSE(result.has_error()); + EXPECT_TRUE(result.value()); +} + +TEST(UrlLauncherPlugin, CanLaunchQueryFailure) { + std::unique_ptr system = std::make_unique(); + + // Return success values from the registery commands, except for the query, + // to simulate a scheme that is in the registry, but has no URL handler. + HKEY fake_key = reinterpret_cast(1); + EXPECT_CALL(*system, RegOpenKeyExW) + .WillOnce(DoAll(SetArgPointee<4>(fake_key), Return(ERROR_SUCCESS))); + EXPECT_CALL(*system, RegQueryValueExW).WillOnce(Return(ERROR_FILE_NOT_FOUND)); + EXPECT_CALL(*system, RegCloseKey(fake_key)).WillOnce(Return(ERROR_SUCCESS)); + + UrlLauncherPlugin plugin(std::move(system)); + ErrorOr result = plugin.CanLaunchUrl("https://some.url.com"); + + ASSERT_FALSE(result.has_error()); + EXPECT_FALSE(result.value()); +} + +TEST(UrlLauncherPlugin, CanLaunchHandlesOpenFailure) { + std::unique_ptr system = std::make_unique(); + + // Return failure for opening. + EXPECT_CALL(*system, RegOpenKeyExW).WillOnce(Return(ERROR_BAD_PATHNAME)); + + UrlLauncherPlugin plugin(std::move(system)); + ErrorOr result = plugin.CanLaunchUrl("https://some.url.com"); + + ASSERT_FALSE(result.has_error()); + EXPECT_FALSE(result.value()); +} + +TEST(UrlLauncherPlugin, LaunchReportsSuccess) { + std::unique_ptr system = std::make_unique(); + + // Return a success value (>32) from launching. + EXPECT_CALL(*system, ShellExecuteW) + .WillOnce(Return(reinterpret_cast(33))); + + UrlLauncherPlugin plugin(std::move(system)); + ErrorOr result = plugin.LaunchUrl("https://some.url.com"); + + ASSERT_FALSE(result.has_error()); + EXPECT_TRUE(result.value()); +} + +TEST(UrlLauncherPlugin, LaunchReportsFailure) { + std::unique_ptr system = std::make_unique(); + + // Return error 31 from launching, indicating no handler. + EXPECT_CALL(*system, ShellExecuteW) + .WillOnce(Return(reinterpret_cast(SE_ERR_NOASSOC))); + + UrlLauncherPlugin plugin(std::move(system)); + ErrorOr result = plugin.LaunchUrl("https://some.url.com"); + + ASSERT_FALSE(result.has_error()); + EXPECT_FALSE(result.value()); +} + +TEST(UrlLauncherPlugin, LaunchReportsError) { + std::unique_ptr system = std::make_unique(); + + // Return a failure value (<=32) from launching. + EXPECT_CALL(*system, ShellExecuteW) + .WillOnce(Return(reinterpret_cast(32))); + + UrlLauncherPlugin plugin(std::move(system)); + ErrorOr result = plugin.LaunchUrl("https://some.url.com"); + + EXPECT_TRUE(result.has_error()); +} + +TEST(UrlLauncherPlugin, LaunchUTF8EncodedFileURLSuccess) { + std::unique_ptr system = std::make_unique(); + + // Return a success value (>32) from launching. + EXPECT_CALL( + *system, + ShellExecuteW( + _, StrEq(L"open"), + // 家の管理/スキャナ"), + StrEq( + L"file:///G:/\x5bb6\x306e\x7ba1\x7406/\x30b9\x30ad\x30e3\x30ca"), + _, _, _)) + .WillOnce(Return(reinterpret_cast(33))); + + UrlLauncherPlugin plugin(std::move(system)); + ErrorOr result = plugin.LaunchUrl( + "file:///G:/%E5%AE%B6%E3%81%AE%E7%AE%A1%E7%90%86/" + "%E3%82%B9%E3%82%AD%E3%83%A3%E3%83%8A"); + + ASSERT_FALSE(result.has_error()); + EXPECT_TRUE(result.value()); +} + +TEST(UrlLauncherPlugin, LaunchUTF8LogsUnescapedOnFail) { + std::unique_ptr system = std::make_unique(); + + // Return a failure value (<32) from launching. + EXPECT_CALL( + *system, + ShellExecuteW( + _, StrEq(L"open"), + // 家の管理/スキャナ"), + StrEq( + L"file:///G:/\x5bb6\x306e\x7ba1\x7406/\x30b9\x30ad\x30e3\x30ca"), + _, _, _)) + .WillOnce(Return(reinterpret_cast(0))); + + UrlLauncherPlugin plugin(std::move(system)); + ErrorOr result = plugin.LaunchUrl( + "file:///G:/%E5%AE%B6%E3%81%AE%E7%AE%A1%E7%90%86/" + "%E3%82%B9%E3%82%AD%E3%83%A3%E3%83%8A"); + + ASSERT_TRUE(result.has_error()); + EXPECT_THAT(result.error().message(), HasSubstr("家の管理/スキャナ")); +} + +} // namespace test +} // namespace url_launcher_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/url_launcher_plugin.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/url_launcher_plugin.cpp new file mode 100755 index 00000000..373e1f36 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/url_launcher_plugin.cpp @@ -0,0 +1,137 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "url_launcher_plugin.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "messages.g.h" + +namespace url_launcher_windows { + +namespace { + +using flutter::EncodableMap; +using flutter::EncodableValue; + +// Converts the given UTF-8 string to UTF-16. +std::wstring Utf16FromUtf8(const std::string& utf8_string) { + if (utf8_string.empty()) { + return std::wstring(); + } + int target_length = + ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(), + static_cast(utf8_string.length()), nullptr, 0); + if (target_length == 0) { + return std::wstring(); + } + std::wstring utf16_string; + utf16_string.resize(target_length); + int converted_length = + ::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(), + static_cast(utf8_string.length()), + utf16_string.data(), target_length); + if (converted_length == 0) { + return std::wstring(); + } + return utf16_string; +} + +// Returns the URL argument from |method_call| if it is present, otherwise +// returns an empty string. +std::string GetUrlArgument(const flutter::MethodCall<>& method_call) { + std::string url; + const auto* arguments = std::get_if(method_call.arguments()); + if (arguments) { + auto url_it = arguments->find(EncodableValue("url")); + if (url_it != arguments->end()) { + url = std::get(url_it->second); + } + } + return url; +} + +} // namespace + +// static +void UrlLauncherPlugin::RegisterWithRegistrar( + flutter::PluginRegistrar* registrar) { + std::unique_ptr plugin = + std::make_unique(); + UrlLauncherApi::SetUp(registrar->messenger(), plugin.get()); + registrar->AddPlugin(std::move(plugin)); +} + +UrlLauncherPlugin::UrlLauncherPlugin() + : system_apis_(std::make_unique()) {} + +UrlLauncherPlugin::UrlLauncherPlugin(std::unique_ptr system_apis) + : system_apis_(std::move(system_apis)) {} + +UrlLauncherPlugin::~UrlLauncherPlugin() = default; + +ErrorOr UrlLauncherPlugin::CanLaunchUrl(const std::string& url) { + size_t separator_location = url.find(":"); + if (separator_location == std::string::npos) { + return false; + } + std::wstring scheme = Utf16FromUtf8(url.substr(0, separator_location)); + + HKEY key = nullptr; + if (system_apis_->RegOpenKeyExW(HKEY_CLASSES_ROOT, scheme.c_str(), 0, + KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) { + return false; + } + bool has_handler = + system_apis_->RegQueryValueExW(key, L"URL Protocol", nullptr, nullptr, + nullptr) == ERROR_SUCCESS; + system_apis_->RegCloseKey(key); + return has_handler; +} + +ErrorOr UrlLauncherPlugin::LaunchUrl(const std::string& url) { + std::string url_to_open; + if (url.find("file:") == 0) { + // ShellExecuteW does not process %-encoded UTF8 strings in file URLs. + DWORD unescaped_len = 0; + std::string unescaped_url = url; + if (FAILED(::UrlUnescapeA(unescaped_url.data(), /*pszUnescaped=*/nullptr, + &unescaped_len, URL_UNESCAPE_INPLACE))) { + return FlutterError("open_error", "Failed to unescape file URL"); + } + url_to_open = unescaped_url; + } else { + url_to_open = url; + } + + int status = + static_cast(reinterpret_cast(system_apis_->ShellExecuteW( + nullptr, TEXT("open"), Utf16FromUtf8(url_to_open).c_str(), nullptr, + nullptr, SW_SHOWNORMAL))); + + // Per ::ShellExecuteW documentation, anything >32 indicates success. + if (status <= 32) { + if (status == SE_ERR_NOASSOC) { + // NOASSOC just means there's nothing registered to handle launching; + // return false rather than an error for better consistency with other + // platforms. + return false; + } + std::ostringstream error_message; + error_message << "Failed to open " << url_to_open + << ": ShellExecute error code " << status; + return FlutterError("open_error", error_message.str()); + } + return true; +} + +} // namespace url_launcher_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/url_launcher_plugin.h b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/url_launcher_plugin.h new file mode 100755 index 00000000..5250c191 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/url_launcher_plugin.h @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include +#include +#include + +#include +#include +#include +#include + +#include "messages.g.h" +#include "system_apis.h" + +namespace url_launcher_windows { + +class UrlLauncherPlugin : public flutter::Plugin, public UrlLauncherApi { + public: + static void RegisterWithRegistrar(flutter::PluginRegistrar* registrar); + + UrlLauncherPlugin(); + + // Creates a plugin instance with the given SystemApi instance. + // + // Exists for unit testing with mock implementations. + UrlLauncherPlugin(std::unique_ptr system_apis); + + virtual ~UrlLauncherPlugin(); + + // Disallow copy and move. + UrlLauncherPlugin(const UrlLauncherPlugin&) = delete; + UrlLauncherPlugin& operator=(const UrlLauncherPlugin&) = delete; + + // UrlLauncherApi: + ErrorOr CanLaunchUrl(const std::string& url) override; + ErrorOr LaunchUrl(const std::string& url) override; + + private: + std::unique_ptr system_apis_; +}; + +} // namespace url_launcher_windows diff --git a/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/url_launcher_windows.cpp b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/url_launcher_windows.cpp new file mode 100755 index 00000000..72670938 --- /dev/null +++ b/app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows/windows/url_launcher_windows.cpp @@ -0,0 +1,15 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "include/url_launcher_windows/url_launcher_windows.h" + +#include + +#include "url_launcher_plugin.h" + +void UrlLauncherWindowsRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + url_launcher_windows::UrlLauncherPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} diff --git a/app/windows/flutter/generated_plugin_registrant.cc b/app/windows/flutter/generated_plugin_registrant.cc old mode 100644 new mode 100755 diff --git a/app/windows/flutter/generated_plugin_registrant.h b/app/windows/flutter/generated_plugin_registrant.h old mode 100644 new mode 100755 diff --git a/app/windows/flutter/generated_plugins.cmake b/app/windows/flutter/generated_plugins.cmake old mode 100644 new mode 100755 diff --git a/app/windows/runner/CMakeLists.txt b/app/windows/runner/CMakeLists.txt old mode 100644 new mode 100755 diff --git a/app/windows/runner/Runner.rc b/app/windows/runner/Runner.rc old mode 100644 new mode 100755 diff --git a/app/windows/runner/flutter_window.cpp b/app/windows/runner/flutter_window.cpp old mode 100644 new mode 100755 diff --git a/app/windows/runner/flutter_window.h b/app/windows/runner/flutter_window.h old mode 100644 new mode 100755 diff --git a/app/windows/runner/main.cpp b/app/windows/runner/main.cpp old mode 100644 new mode 100755 diff --git a/app/windows/runner/resource.h b/app/windows/runner/resource.h old mode 100644 new mode 100755 diff --git a/app/windows/runner/resources/app_icon.ico b/app/windows/runner/resources/app_icon.ico old mode 100644 new mode 100755 diff --git a/app/windows/runner/runner.exe.manifest b/app/windows/runner/runner.exe.manifest old mode 100644 new mode 100755 diff --git a/app/windows/runner/utils.cpp b/app/windows/runner/utils.cpp old mode 100644 new mode 100755 diff --git a/app/windows/runner/utils.h b/app/windows/runner/utils.h old mode 100644 new mode 100755 diff --git a/app/windows/runner/win32_window.cpp b/app/windows/runner/win32_window.cpp old mode 100644 new mode 100755 diff --git a/app/windows/runner/win32_window.h b/app/windows/runner/win32_window.h old mode 100644 new mode 100755 diff --git a/app/z_logs.csv b/app/z_logs.csv old mode 100644 new mode 100755 diff --git a/bao/.gitignore b/bao/.gitignore old mode 100644 new mode 100755 diff --git a/bao/DEPLOY.md b/bao/DEPLOY.md old mode 100644 new mode 100755 diff --git a/bao/README.md b/bao/README.md old mode 100644 new mode 100755 diff --git a/bao/config/database.php b/bao/config/database.php old mode 100644 new mode 100755 diff --git a/bao/dump-geo_app-202510011905.sql b/bao/dump-geo_app-202510011905.sql old mode 100644 new mode 100755 diff --git a/bao/dump-geo_app-202510011916.sql b/bao/dump-geo_app-202510011916.sql old mode 100644 new mode 100755 diff --git a/bao/dump-geosector-202510021710.sql b/bao/dump-geosector-202510021710.sql old mode 100644 new mode 100755 diff --git a/bao/dump-geosector-202510021837.sql b/bao/dump-geosector-202510021837.sql old mode 100644 new mode 100755 diff --git a/bao/dump-geosector-202510051844.sql b/bao/dump-geosector-202510051844.sql old mode 100644 new mode 100755 diff --git a/bao/dump-rca_geo-202510261750.sql b/bao/dump-rca_geo-202510261750.sql old mode 100644 new mode 100755 diff --git a/bao/lib/CryptoService.php b/bao/lib/CryptoService.php old mode 100644 new mode 100755 diff --git a/bao/lib/DatabaseConnection.php b/bao/lib/DatabaseConnection.php old mode 100644 new mode 100755 diff --git a/bao/lib/helpers.php b/bao/lib/helpers.php old mode 100644 new mode 100755 diff --git a/bao/lib/init-connection.php b/bao/lib/init-connection.php old mode 100644 new mode 100755 diff --git a/cron/batiments.md b/cron/batiments.md old mode 100644 new mode 100755 diff --git a/cron/doc/CHANGELOG.md b/cron/doc/CHANGELOG.md old mode 100644 new mode 100755 diff --git a/cron/doc/README.md b/cron/doc/README.md old mode 100644 new mode 100755 diff --git a/cron/doc/documentation.xlsx b/cron/doc/documentation.xlsx old mode 100644 new mode 100755 diff --git a/cron/dump-adresses-202511061203.sql b/cron/dump-adresses-202511061203.sql old mode 100644 new mode 100755 diff --git a/cron/init_batiments.sql b/cron/init_batiments.sql old mode 100644 new mode 100755 diff --git a/cron/test_batiments_35.sh b/cron/test_batiments_35.sh old mode 100644 new mode 100755 diff --git a/cron/traite_adresses.sh b/cron/traite_adresses.sh old mode 100644 new mode 100755 diff --git a/cron/traite_batiments.sh b/cron/traite_batiments.sh old mode 100644 new mode 100755 diff --git a/cron/traite_batiments.sql b/cron/traite_batiments.sql old mode 100644 new mode 100755 diff --git a/cron/traite_osm.sh b/cron/traite_osm.sh old mode 100644 new mode 100755 diff --git a/docs/planning-geosector-q1-2026.xls b/docs/planning-geosector-q1-2026.xls old mode 100644 new mode 100755 diff --git a/testeurs_alpha.csv b/testeurs_alpha.csv old mode 100644 new mode 100755