mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Show Mac Designed For iPad in 'flutter devices' (#141718)
Addresses https://github.com/flutter/flutter/issues/141290 by allow Mac Designed For IPad Devices to appear with 'flutter devices'. <img width="573" alt="Screenshot 2024-01-29 at 12 23 24â¯AM" src="https://github.com/flutter/flutter/assets/36148254/35709a93-56fc-44c9-98d5-cf45afce967d"> <img width="725" alt="Screenshot 2024-01-29 at 12 26 01â¯AM" src="https://github.com/flutter/flutter/assets/36148254/b6cbcfce-44db-42c6-ac01-0ab716d30373">
This commit is contained in:
parent
071830663a
commit
42317804ee
@ -213,9 +213,6 @@ known, it can be explicitly provided to attach via the command-line, e.g.
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> validateCommand() async {
|
Future<void> validateCommand() async {
|
||||||
// ARM macOS as an iOS target is hidden, except for attach.
|
|
||||||
MacOSDesignedForIPadDevices.allowDiscovery = true;
|
|
||||||
|
|
||||||
await super.validateCommand();
|
await super.validateCommand();
|
||||||
|
|
||||||
final Device? targetDevice = await findTargetDevice();
|
final Device? targetDevice = await findTargetDevice();
|
||||||
|
@ -25,6 +25,7 @@ import '../drive/drive_service.dart';
|
|||||||
import '../drive/web_driver_service.dart' show Browser;
|
import '../drive/web_driver_service.dart' show Browser;
|
||||||
import '../globals.dart' as globals;
|
import '../globals.dart' as globals;
|
||||||
import '../ios/devices.dart';
|
import '../ios/devices.dart';
|
||||||
|
import '../macos/macos_ipad_device.dart';
|
||||||
import '../resident_runner.dart';
|
import '../resident_runner.dart';
|
||||||
import '../runner/flutter_command.dart' show FlutterCommandCategory, FlutterCommandResult, FlutterOptions;
|
import '../runner/flutter_command.dart' show FlutterCommandCategory, FlutterCommandResult, FlutterOptions;
|
||||||
import '../web/web_device.dart';
|
import '../web/web_device.dart';
|
||||||
@ -222,6 +223,9 @@ class DriveCommand extends RunCommandBase {
|
|||||||
if (device is! AndroidDevice) {
|
if (device is! AndroidDevice) {
|
||||||
throwToolExit('--${FlutterOptions.kDeviceUser} is only supported for Android');
|
throwToolExit('--${FlutterOptions.kDeviceUser} is only supported for Android');
|
||||||
}
|
}
|
||||||
|
if (device is MacOSDesignedForIPadDevice) {
|
||||||
|
throwToolExit('Mac Designed for iPad is currently not supported for flutter drive.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return super.validateCommand();
|
return super.validateCommand();
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import '../device.dart';
|
|||||||
import '../features.dart';
|
import '../features.dart';
|
||||||
import '../globals.dart' as globals;
|
import '../globals.dart' as globals;
|
||||||
import '../ios/devices.dart';
|
import '../ios/devices.dart';
|
||||||
|
import '../macos/macos_ipad_device.dart';
|
||||||
import '../project.dart';
|
import '../project.dart';
|
||||||
import '../reporting/reporting.dart';
|
import '../reporting/reporting.dart';
|
||||||
import '../resident_runner.dart';
|
import '../resident_runner.dart';
|
||||||
@ -591,6 +592,15 @@ class RunCommand extends RunCommandBase {
|
|||||||
if (devices == null) {
|
if (devices == null) {
|
||||||
throwToolExit(null);
|
throwToolExit(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (devices!.length == 1 && devices!.first is MacOSDesignedForIPadDevice) {
|
||||||
|
throwToolExit('Mac Designed for iPad is currently not supported for flutter run -d.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globals.deviceManager!.hasSpecifiedAllDevices) {
|
||||||
|
devices?.removeWhere((Device device) => device is MacOSDesignedForIPadDevice);
|
||||||
|
}
|
||||||
|
|
||||||
if (globals.deviceManager!.hasSpecifiedAllDevices && runningWithPrebuiltApplication) {
|
if (globals.deviceManager!.hasSpecifiedAllDevices && runningWithPrebuiltApplication) {
|
||||||
throwToolExit('Using "-d all" with "--${FlutterOptions.kUseApplicationBinary}" is not supported');
|
throwToolExit('Using "-d all" with "--${FlutterOptions.kUseApplicationBinary}" is not supported');
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class MacOSDesignedForIPadDevice extends DesktopDevice {
|
|||||||
required OperatingSystemUtils operatingSystemUtils,
|
required OperatingSystemUtils operatingSystemUtils,
|
||||||
}) : _operatingSystemUtils = operatingSystemUtils,
|
}) : _operatingSystemUtils = operatingSystemUtils,
|
||||||
super(
|
super(
|
||||||
'designed-for-ipad',
|
'mac-designed-for-ipad',
|
||||||
platformType: PlatformType.macos,
|
platformType: PlatformType.macos,
|
||||||
ephemeral: false,
|
ephemeral: false,
|
||||||
processManager: processManager,
|
processManager: processManager,
|
||||||
@ -120,10 +120,7 @@ class MacOSDesignedForIPadDevices extends PollingDeviceDiscovery {
|
|||||||
/// and discovery is allowed for this command.
|
/// and discovery is allowed for this command.
|
||||||
@override
|
@override
|
||||||
bool get canListAnything =>
|
bool get canListAnything =>
|
||||||
_iosWorkflow.canListDevices && _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm64 && allowDiscovery;
|
_iosWorkflow.canListDevices && _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm64;
|
||||||
|
|
||||||
/// Set to show ARM macOS as an iOS device target.
|
|
||||||
static bool allowDiscovery = false;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<Device>> pollingGetDevices({Duration? timeout}) async {
|
Future<List<Device>> pollingGetDevices({Duration? timeout}) async {
|
||||||
@ -144,5 +141,5 @@ class MacOSDesignedForIPadDevices extends PollingDeviceDiscovery {
|
|||||||
Future<List<String>> getDiagnostics() async => const <String>[];
|
Future<List<String>> getDiagnostics() async => const <String>[];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> get wellKnownIds => const <String>['designed-for-ipad'];
|
List<String> get wellKnownIds => const <String>['mac-designed-for-ipad'];
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import 'package:flutter_tools/src/device.dart';
|
|||||||
import 'package:flutter_tools/src/device_port_forwarder.dart';
|
import 'package:flutter_tools/src/device_port_forwarder.dart';
|
||||||
import 'package:flutter_tools/src/ios/application_package.dart';
|
import 'package:flutter_tools/src/ios/application_package.dart';
|
||||||
import 'package:flutter_tools/src/ios/devices.dart';
|
import 'package:flutter_tools/src/ios/devices.dart';
|
||||||
import 'package:flutter_tools/src/macos/macos_ipad_device.dart';
|
|
||||||
import 'package:flutter_tools/src/mdns_discovery.dart';
|
import 'package:flutter_tools/src/mdns_discovery.dart';
|
||||||
import 'package:flutter_tools/src/project.dart';
|
import 'package:flutter_tools/src/project.dart';
|
||||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||||
@ -52,10 +51,6 @@ class FakeProcessInfo extends Fake implements ProcessInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
tearDown(() {
|
|
||||||
MacOSDesignedForIPadDevices.allowDiscovery = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
group('attach', () {
|
group('attach', () {
|
||||||
late StreamLogger logger;
|
late StreamLogger logger;
|
||||||
late FileSystem testFileSystem;
|
late FileSystem testFileSystem;
|
||||||
@ -1067,7 +1062,6 @@ void main() {
|
|||||||
expect(testLogger.statusText, containsIgnoringWhitespace('More than one device'));
|
expect(testLogger.statusText, containsIgnoringWhitespace('More than one device'));
|
||||||
expect(testLogger.statusText, contains('xx1'));
|
expect(testLogger.statusText, contains('xx1'));
|
||||||
expect(testLogger.statusText, contains('yy2'));
|
expect(testLogger.statusText, contains('yy2'));
|
||||||
expect(MacOSDesignedForIPadDevices.allowDiscovery, isTrue);
|
|
||||||
}, overrides: <Type, Generator>{
|
}, overrides: <Type, Generator>{
|
||||||
FileSystem: () => testFileSystem,
|
FileSystem: () => testFileSystem,
|
||||||
ProcessManager: () => FakeProcessManager.any(),
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
|
@ -25,6 +25,7 @@ import 'package:flutter_tools/src/devfs.dart';
|
|||||||
import 'package:flutter_tools/src/device.dart';
|
import 'package:flutter_tools/src/device.dart';
|
||||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||||
import 'package:flutter_tools/src/ios/devices.dart';
|
import 'package:flutter_tools/src/ios/devices.dart';
|
||||||
|
import 'package:flutter_tools/src/macos/macos_ipad_device.dart';
|
||||||
import 'package:flutter_tools/src/project.dart';
|
import 'package:flutter_tools/src/project.dart';
|
||||||
import 'package:flutter_tools/src/reporting/reporting.dart';
|
import 'package:flutter_tools/src/reporting/reporting.dart';
|
||||||
import 'package:flutter_tools/src/resident_runner.dart';
|
import 'package:flutter_tools/src/resident_runner.dart';
|
||||||
@ -242,6 +243,62 @@ void main() {
|
|||||||
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
|
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testUsingContext('Using flutter run -d with MacOSDesignedForIPadDevices throws an error', () async {
|
||||||
|
final RunCommand command = RunCommand();
|
||||||
|
testDeviceManager.devices = <Device>[FakeMacDesignedForIpadDevice()];
|
||||||
|
|
||||||
|
await expectLater(
|
||||||
|
() => createTestCommandRunner(command).run(<String>[
|
||||||
|
'run',
|
||||||
|
'-d',
|
||||||
|
'mac-designed-for-ipad',
|
||||||
|
]), throwsToolExit(message: 'Mac Designed for iPad is currently not supported for flutter run -d'));
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
FileSystem: () => fs,
|
||||||
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
|
DeviceManager: () => testDeviceManager,
|
||||||
|
Stdio: () => FakeStdio(),
|
||||||
|
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('Using flutter run -d all with a single MacOSDesignedForIPadDevices throws a tool error', () async {
|
||||||
|
final RunCommand command = RunCommand();
|
||||||
|
testDeviceManager.devices = <Device>[FakeMacDesignedForIpadDevice()];
|
||||||
|
|
||||||
|
await expectLater(
|
||||||
|
() => createTestCommandRunner(command).run(<String>[
|
||||||
|
'run',
|
||||||
|
'-d',
|
||||||
|
'all',
|
||||||
|
]), throwsToolExit(message: 'Mac Designed for iPad is currently not supported for flutter run -d'));
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
FileSystem: () => fs,
|
||||||
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
|
DeviceManager: () => testDeviceManager,
|
||||||
|
Stdio: () => FakeStdio(),
|
||||||
|
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('Using flutter run -d all with MacOSDesignedForIPadDevices removes from device list, and attempts to launch', () async {
|
||||||
|
final RunCommand command = TestRunCommandThatOnlyValidates();
|
||||||
|
testDeviceManager.devices = <Device>[FakeMacDesignedForIpadDevice(), FakeDevice()];
|
||||||
|
|
||||||
|
await createTestCommandRunner(command).run(<String>[
|
||||||
|
'run',
|
||||||
|
'-d',
|
||||||
|
'all',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(command.devices?.length, 1);
|
||||||
|
expect(command.devices?.single.id, 'fake_device');
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
FileSystem: () => fs,
|
||||||
|
ProcessManager: () => FakeProcessManager.any(),
|
||||||
|
DeviceManager: () => testDeviceManager,
|
||||||
|
Stdio: () => FakeStdio(),
|
||||||
|
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
|
||||||
|
});
|
||||||
|
|
||||||
testUsingContext('exits and lists available devices when specified device not found', () async {
|
testUsingContext('exits and lists available devices when specified device not found', () async {
|
||||||
final RunCommand command = RunCommand();
|
final RunCommand command = RunCommand();
|
||||||
final FakeDevice device = FakeDevice(isLocalEmulator: true);
|
final FakeDevice device = FakeDevice(isLocalEmulator: true);
|
||||||
@ -1413,6 +1470,27 @@ class FakeDevice extends Fake implements Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FakeMacDesignedForIpadDevice extends Fake implements MacOSDesignedForIPadDevice {
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get id => 'mac-designed-for-ipad';
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isConnected => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<TargetPlatform> get targetPlatform async => TargetPlatform.darwin;
|
||||||
|
|
||||||
|
@override
|
||||||
|
DeviceConnectionInterface connectionInterface = DeviceConnectionInterface.attached;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isSupported() => true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isSupportedForProject(FlutterProject project) => true;
|
||||||
|
}
|
||||||
|
|
||||||
class FakeIOSDevice extends Fake implements IOSDevice {
|
class FakeIOSDevice extends Fake implements IOSDevice {
|
||||||
FakeIOSDevice({
|
FakeIOSDevice({
|
||||||
this.connectionInterface = DeviceConnectionInterface.attached,
|
this.connectionInterface = DeviceConnectionInterface.attached,
|
||||||
@ -1479,6 +1557,9 @@ class TestRunCommandThatOnlyValidates extends RunCommand {
|
|||||||
Future<FlutterCommandResult> runCommand() async {
|
Future<FlutterCommandResult> runCommand() async {
|
||||||
return FlutterCommandResult.success();
|
return FlutterCommandResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get shouldRunPub => false;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeResidentRunner extends Fake implements ResidentRunner {
|
class FakeResidentRunner extends Fake implements ResidentRunner {
|
||||||
|
@ -21,12 +21,7 @@ import '../../src/fakes.dart';
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('MacOSDesignedForIPadDevices', () {
|
group('MacOSDesignedForIPadDevices', () {
|
||||||
tearDown(() {
|
|
||||||
MacOSDesignedForIPadDevices.allowDiscovery = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
testWithoutContext('does not support non-macOS platforms', () async {
|
testWithoutContext('does not support non-macOS platforms', () async {
|
||||||
MacOSDesignedForIPadDevices.allowDiscovery = true;
|
|
||||||
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
||||||
platform: FakePlatform(operatingSystem: 'windows'),
|
platform: FakePlatform(operatingSystem: 'windows'),
|
||||||
logger: BufferLogger.test(),
|
logger: BufferLogger.test(),
|
||||||
@ -39,7 +34,7 @@ void main() {
|
|||||||
expect(discoverer.supportsPlatform, isFalse);
|
expect(discoverer.supportsPlatform, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('discovery not allowed', () async {
|
testWithoutContext('discovery is allowed', () async {
|
||||||
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
||||||
platform: FakePlatform(operatingSystem: 'macos'),
|
platform: FakePlatform(operatingSystem: 'macos'),
|
||||||
logger: BufferLogger.test(),
|
logger: BufferLogger.test(),
|
||||||
@ -51,11 +46,12 @@ void main() {
|
|||||||
expect(discoverer.supportsPlatform, isTrue);
|
expect(discoverer.supportsPlatform, isTrue);
|
||||||
|
|
||||||
final List<Device> devices = await discoverer.devices();
|
final List<Device> devices = await discoverer.devices();
|
||||||
expect(devices, isEmpty);
|
expect(devices, isNotNull);
|
||||||
|
expect(devices.first.id, 'mac-designed-for-ipad');
|
||||||
|
expect(devices.first is MacOSDesignedForIPadDevice, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('no device on x86', () async {
|
testWithoutContext('no device on x86', () async {
|
||||||
MacOSDesignedForIPadDevices.allowDiscovery = true;
|
|
||||||
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
||||||
platform: FakePlatform(operatingSystem: 'macos'),
|
platform: FakePlatform(operatingSystem: 'macos'),
|
||||||
logger: BufferLogger.test(),
|
logger: BufferLogger.test(),
|
||||||
@ -71,7 +67,6 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('no device on when iOS development off', () async {
|
testWithoutContext('no device on when iOS development off', () async {
|
||||||
MacOSDesignedForIPadDevices.allowDiscovery = true;
|
|
||||||
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
||||||
platform: FakePlatform(operatingSystem: 'macos'),
|
platform: FakePlatform(operatingSystem: 'macos'),
|
||||||
logger: BufferLogger.test(),
|
logger: BufferLogger.test(),
|
||||||
@ -87,7 +82,6 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWithoutContext('device discovery on arm', () async {
|
testWithoutContext('device discovery on arm', () async {
|
||||||
MacOSDesignedForIPadDevices.allowDiscovery = true;
|
|
||||||
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
final MacOSDesignedForIPadDevices discoverer = MacOSDesignedForIPadDevices(
|
||||||
platform: FakePlatform(operatingSystem: 'macos'),
|
platform: FakePlatform(operatingSystem: 'macos'),
|
||||||
logger: BufferLogger.test(),
|
logger: BufferLogger.test(),
|
||||||
@ -103,7 +97,7 @@ void main() {
|
|||||||
|
|
||||||
final Device device = devices.single;
|
final Device device = devices.single;
|
||||||
expect(device, isA<MacOSDesignedForIPadDevice>());
|
expect(device, isA<MacOSDesignedForIPadDevice>());
|
||||||
expect(device.id, 'designed-for-ipad');
|
expect(device.id, 'mac-designed-for-ipad');
|
||||||
|
|
||||||
// Timeout ignored.
|
// Timeout ignored.
|
||||||
devices = await discoverer.discoverDevices(timeout: const Duration(seconds: 10));
|
devices = await discoverer.discoverDevices(timeout: const Duration(seconds: 10));
|
||||||
@ -118,7 +112,7 @@ void main() {
|
|||||||
fileSystem: MemoryFileSystem.test(),
|
fileSystem: MemoryFileSystem.test(),
|
||||||
operatingSystemUtils: FakeOperatingSystemUtils(hostPlatform: HostPlatform.darwin_arm64),
|
operatingSystemUtils: FakeOperatingSystemUtils(hostPlatform: HostPlatform.darwin_arm64),
|
||||||
);
|
);
|
||||||
expect(device.id, 'designed-for-ipad');
|
expect(device.id, 'mac-designed-for-ipad');
|
||||||
expect(await device.isLocalEmulator, isFalse);
|
expect(await device.isLocalEmulator, isFalse);
|
||||||
expect(device.name, 'Mac Designed for iPad');
|
expect(device.name, 'Mac Designed for iPad');
|
||||||
expect(device.portForwarder, isNot(isNull));
|
expect(device.portForwarder, isNot(isNull));
|
||||||
|
Loading…
Reference in New Issue
Block a user