diff --git a/ios_widget_catalog_compare/analysis_options.yaml b/ios_widget_catalog_compare/analysis_options.yaml new file mode 100644 index 0000000..460c196 --- /dev/null +++ b/ios_widget_catalog_compare/analysis_options.yaml @@ -0,0 +1,33 @@ +# 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 + +analyzer: + exclude: + - build/** + - ios/** + +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.dev/lints. + # + # 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/ios_widget_catalog_compare/ios/Flutter/AppFrameworkInfo.plist b/ios_widget_catalog_compare/ios/Flutter/AppFrameworkInfo.plist index f2872cf..ab8e063 100644 --- a/ios_widget_catalog_compare/ios/Flutter/AppFrameworkInfo.plist +++ b/ios_widget_catalog_compare/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 9.0 diff --git a/ios_widget_catalog_compare/ios/Runner.xcodeproj/project.pbxproj b/ios_widget_catalog_compare/ios/Runner.xcodeproj/project.pbxproj index 9bddab7..92bcfc7 100644 --- a/ios_widget_catalog_compare/ios/Runner.xcodeproj/project.pbxproj +++ b/ios_widget_catalog_compare/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -141,7 +141,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -185,10 +185,12 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( @@ -199,6 +201,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -288,7 +291,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -373,7 +376,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -422,7 +425,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -518,4 +521,4 @@ /* End XCConfigurationList section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; -} \ No newline at end of file +} diff --git a/ios_widget_catalog_compare/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios_widget_catalog_compare/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140c..fc5ae03 100644 --- a/ios_widget_catalog_compare/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/ios_widget_catalog_compare/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ @@ -45,11 +46,13 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> diff --git a/ios_widget_catalog_compare/ios/Runner/AppDelegate.swift b/ios_widget_catalog_compare/ios/Runner/AppDelegate.swift index 7b1454e..5958679 100644 --- a/ios_widget_catalog_compare/ios/Runner/AppDelegate.swift +++ b/ios_widget_catalog_compare/ios/Runner/AppDelegate.swift @@ -5,7 +5,7 @@ import UIKit import Flutter -@UIApplicationMain +@main @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, diff --git a/ios_widget_catalog_compare/ios/Runner/Info.plist b/ios_widget_catalog_compare/ios/Runner/Info.plist index cf3534f..b96b9bb 100644 --- a/ios_widget_catalog_compare/ios/Runner/Info.plist +++ b/ios_widget_catalog_compare/ios/Runner/Info.plist @@ -41,5 +41,9 @@ UIViewControllerBasedStatusBarAppearance + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + diff --git a/ios_widget_catalog_compare/lib/main.dart b/ios_widget_catalog_compare/lib/main.dart index 0cbcd4c..01adeb5 100644 --- a/ios_widget_catalog_compare/lib/main.dart +++ b/ios_widget_catalog_compare/lib/main.dart @@ -5,23 +5,19 @@ import 'package:flutter/services.dart'; import 'package:flutter/cupertino.dart'; -const EventChannel _platformEventChannel = - const EventChannel('overlay_ios.flutter.io/responder'); +const EventChannel _platformEventChannel = EventChannel( + 'overlay_ios.flutter.io/responder', +); void main() { - runApp( - CupertinoApp( - title: 'Flutter Demo', - home: FlutterDemo(), - ), - ); + runApp(CupertinoApp(title: 'Flutter Demo', home: FlutterDemo())); } class FlutterDemo extends StatefulWidget { - FlutterDemo({super.key}); + const FlutterDemo({super.key}); @override - _FlutterDemoState createState() => _FlutterDemoState(); + State createState() => _FlutterDemoState(); } class _FlutterDemoState extends State { @@ -59,13 +55,13 @@ class _FlutterDemoState extends State { case 'CupertinoButton': return CupertinoButton( child: Text('Button'), - onPressed: () {/** */}, + onPressed: () { + /** */ + }, ); case 'CupertinoTextField': - return CupertinoTextField( - placeholder: "Placeholder", - ); + return CupertinoTextField(placeholder: "Placeholder"); case 'CupertinoPicker': return CupertinoPicker( @@ -87,10 +83,10 @@ class _FlutterDemoState extends State { return CupertinoSearchTextField( controller: textController, onChanged: (value) { - print("The text has changed to: " + value); + debugPrint("The text has changed to: $value"); }, onSubmitted: (value) { - print("Submitted text: " + value); + debugPrint("Submitted text: $value"); }, ); @@ -153,10 +149,10 @@ class _FlutterDemoState extends State { CupertinoFormRow( prefix: Text('Toggle'), child: CupertinoSwitch( - value: this.toggleValue, + value: toggleValue, onChanged: (value) { setState(() { - this.toggleValue = value; + toggleValue = value; }); }, ), @@ -165,7 +161,9 @@ class _FlutterDemoState extends State { ), Padding( padding: const EdgeInsets.symmetric( - vertical: 16.0, horizontal: 16.0), + vertical: 16.0, + horizontal: 16.0, + ), child: CupertinoButton( onPressed: () { if (_formKey.currentState?.validate() ?? false) { @@ -175,8 +173,9 @@ class _FlutterDemoState extends State { title: Text('Validated'), actions: [ CupertinoDialogAction( - child: Text('Ok'), - onPressed: () => Navigator.pop(context)), + child: Text('Ok'), + onPressed: () => Navigator.pop(context), + ), ], ), ); @@ -249,10 +248,10 @@ class _FlutterDemoState extends State { CupertinoFormRow( prefix: Text('Toggle'), child: CupertinoSwitch( - value: this.toggleValue, + value: toggleValue, onChanged: (value) { setState(() { - this.toggleValue = value; + toggleValue = value; }); }, ), @@ -261,7 +260,9 @@ class _FlutterDemoState extends State { ), Padding( padding: const EdgeInsets.symmetric( - vertical: 16.0, horizontal: 16.0), + vertical: 16.0, + horizontal: 16.0, + ), child: CupertinoButton( onPressed: () { if (_formKey.currentState?.validate() ?? false) { @@ -271,8 +272,9 @@ class _FlutterDemoState extends State { title: Text('Validated'), actions: [ CupertinoDialogAction( - child: Text('Ok'), - onPressed: () => Navigator.pop(context)), + child: Text('Ok'), + onPressed: () => Navigator.pop(context), + ), ], ), ); diff --git a/ios_widget_catalog_compare/pubspec.lock b/ios_widget_catalog_compare/pubspec.lock index 1f77e4f..64fbd42 100644 --- a/ios_widget_catalog_compare/pubspec.lock +++ b/ios_widget_catalog_compare/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.13.1" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: @@ -29,10 +29,10 @@ packages: dependency: transitive description: name: clock - sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.3" collection: dependency: transitive description: @@ -45,10 +45,10 @@ packages: dependency: "direct main" description: name: cupertino_icons - sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" + sha256: b7cc2390aac296c083bea762859413eb1cf5b630c70e0c7e4d831018f762a8b2 url: "https://pub.dev" source: hosted - version: "1.0.9" + version: "2.0.0" fake_async: dependency: transitive description: @@ -62,6 +62,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -91,14 +99,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + lints: + dependency: transitive + description: + name: lints + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" + url: "https://pub.dev" + source: hosted + version: "6.1.0" matcher: dependency: transitive description: name: matcher - sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" url: "https://pub.dev" source: hosted - version: "0.12.19" + version: "0.12.20" material_color_utilities: dependency: transitive description: @@ -111,10 +127,10 @@ packages: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9" url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.19.0" path: dependency: transitive description: @@ -132,18 +148,18 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.2" stack_trace: dependency: transitive description: name: stack_trace - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490" url: "https://pub.dev" source: hosted - version: "1.12.1" + version: "1.12.2" stream_channel: dependency: transitive description: @@ -156,42 +172,42 @@ packages: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "1.4.1" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" + sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" url: "https://pub.dev" source: hosted - version: "0.7.10" + version: "0.7.12" vector_math: dependency: transitive description: name: vector_math - sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + sha256: "92b9910f66ed1057fd4da7b040ae7c74cafacf885bdc81be496928d5049b032d" url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.4.3" vm_service: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: "89b11d62e1040ee681af3b4f1c97a803ecbf010c6e8b9c5896ee5b08c3bf7b78" url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "15.4.0" sdks: - dart: ">=3.4.0 <4.0.0" + dart: ">=3.13.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/ios_widget_catalog_compare/pubspec.yaml b/ios_widget_catalog_compare/pubspec.yaml index 8c6b8c4..a50b455 100644 --- a/ios_widget_catalog_compare/pubspec.yaml +++ b/ios_widget_catalog_compare/pubspec.yaml @@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=3.0.0" + sdk: ^3.13.0 dependencies: flutter: @@ -27,12 +27,19 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.9 + cupertino_icons: ^2.0.0 dev_dependencies: flutter_test: sdk: flutter + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^6.0.0 + # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/ios_widget_catalog_compare/test/smoke_test.dart b/ios_widget_catalog_compare/test/smoke_test.dart new file mode 100644 index 0000000..847161a --- /dev/null +++ b/ios_widget_catalog_compare/test/smoke_test.dart @@ -0,0 +1,71 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:overlay_ios/main.dart'; + +void main() { + // The names the native overlay sends (the keys of controlDictionary in + // ios/Runner/OverlaySwiftUIView.swift), each with the widget type that + // widgetPicker builds for it. Add an entry when adding a control. + const controls = { + 'CupertinoButton': CupertinoButton, + 'CupertinoTextField': CupertinoTextField, + 'CupertinoPicker': CupertinoPicker, + 'CupertinoSearchTextField': CupertinoSearchTextField, + 'CupertinoFormSectionGroupInsetDemo': CupertinoFormSection, + 'CupertinoFormSection': CupertinoFormSection, + 'CupertinoActivityIndicator': CupertinoActivityIndicator, + 'CupertinoSliverNavigationBar': CupertinoSliverNavigationBar, + 'CupertinoSwitch': CupertinoSwitch, + 'CupertinoSlidingSegmentedControl': CupertinoSlidingSegmentedControl, + }; + + testWidgets('shows no control until the platform selects one', ( + WidgetTester tester, + ) async { + await _pumpCatalog(tester); + for (final Type widgetType in controls.values) { + expect(find.byType(widgetType), findsNothing); + } + }); + + for (final MapEntry(key: controlName, value: widgetType) + in controls.entries) { + testWidgets('shows $controlName when the platform selects it', ( + WidgetTester tester, + ) async { + await _pumpCatalog(tester, controlName: controlName); + expect(find.byType(widgetType), findsWidgets); + }); + } +} + +/// Pumps the catalog with a mock of the native overlay. +/// +/// If `controlName` is given, the mock selects it the way the native overlay +/// does, by sending the name over the `overlay_ios.flutter.io/responder` +/// event channel. +Future _pumpCatalog(WidgetTester tester, {String? controlName}) async { + const channel = EventChannel('overlay_ios.flutter.io/responder'); + tester.binding.defaultBinaryMessenger.setMockStreamHandler( + channel, + MockStreamHandler.inline( + onListen: (Object? arguments, MockStreamHandlerEventSink events) { + if (controlName != null) { + events.success(controlName); + } + }, + ), + ); + // Remove the mock so it can't leak into the next test. + addTearDown( + () => tester.binding.defaultBinaryMessenger.setMockStreamHandler( + channel, + null, + ), + ); + await tester.pumpWidget(const CupertinoApp(home: FlutterDemo())); + // Build the frame that a received name schedules. Note we can't use + // pumpAndSettle because CupertinoActivityIndicator animates forever. + await tester.pump(); +}