Skip to content

Commit c94f506

Browse files
committed
feat: add tvOS build and run support
1 parent 5942014 commit c94f506

22 files changed

Lines changed: 225 additions & 32 deletions

lib/bootstrap.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ injector.requireCommand("run|ios", "./commands/run");
183183
injector.requireCommand("run|android", "./commands/run");
184184
injector.requireCommand("run|vision", "./commands/run");
185185
injector.requireCommand("run|visionos", "./commands/run");
186+
injector.requireCommand("run|tvos", "./commands/run");
186187
injector.requireCommand("typings", "./commands/typings");
187188

188189
injector.requireCommand("preview", "./commands/preview");
@@ -198,6 +199,7 @@ injector.requireCommand("build|ios", "./commands/build");
198199
injector.requireCommand("build|android", "./commands/build");
199200
injector.requireCommand("build|vision", "./commands/build");
200201
injector.requireCommand("build|visionos", "./commands/build");
202+
injector.requireCommand("build|tvos", "./commands/build");
201203
injector.requireCommand("deploy", "./commands/deploy");
202204

203205
injector.requireCommand("embed", "./commands/embedding/embed");

lib/commands/build.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,58 @@ export class BuildVisionOsCommand extends BuildIosCommand implements ICommand {
278278

279279
injector.registerCommand("build|vision", BuildVisionOsCommand);
280280
injector.registerCommand("build|visionos", BuildVisionOsCommand);
281+
282+
export class BuildTvOsCommand extends BuildVisionOsCommand implements ICommand {
283+
// The injector resolves dependencies by constructor parameter name, so the
284+
// constructor has to be spelled out even though it only forwards.
285+
constructor(
286+
protected $options: IOptions,
287+
$errors: IErrors,
288+
$projectData: IProjectData,
289+
$platformsDataService: IPlatformsDataService,
290+
$devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
291+
$buildController: IBuildController,
292+
$platformValidationService: IPlatformValidationService,
293+
$logger: ILogger,
294+
$buildDataService: IBuildDataService,
295+
protected $migrateController: IMigrateController,
296+
) {
297+
super(
298+
$options,
299+
$errors,
300+
$projectData,
301+
$platformsDataService,
302+
$devicePlatformsConstants,
303+
$buildController,
304+
$platformValidationService,
305+
$logger,
306+
$buildDataService,
307+
$migrateController,
308+
);
309+
}
310+
311+
public async execute(args: string[]): Promise<void> {
312+
await this.executeCore([this.$devicePlatformsConstants.tvOS.toLowerCase()]);
313+
}
314+
315+
public async canExecute(args: string[]): Promise<boolean> {
316+
const platform = this.$devicePlatformsConstants.tvOS;
317+
if (!this.$options.force) {
318+
await this.$migrateController.validate({
319+
projectDir: this.$projectData.projectDir,
320+
platforms: [platform],
321+
});
322+
}
323+
324+
super.validatePlatform(platform);
325+
326+
let canExecute = await super.canExecuteCommandBase(platform);
327+
if (canExecute) {
328+
canExecute = await super.validateArgs(args, platform);
329+
}
330+
331+
return canExecute;
332+
}
333+
}
334+
335+
injector.registerCommand("build|tvos", BuildTvOsCommand);

lib/commands/run.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,29 @@ export class RunVisionOSCommand extends RunIosCommand {
223223

224224
injector.registerCommand("run|vision", RunVisionOSCommand);
225225
injector.registerCommand("run|visionos", RunVisionOSCommand);
226+
227+
export class RunTvOSCommand extends RunVisionOSCommand {
228+
public get platform(): string {
229+
return this.$devicePlatformsConstants.tvOS;
230+
}
231+
232+
constructor(
233+
protected $devicePlatformsConstants: Mobile.IDevicePlatformsConstants,
234+
protected $errors: IErrors,
235+
protected $injector: IInjector,
236+
protected $options: IOptions,
237+
protected $platformValidationService: IPlatformValidationService,
238+
protected $projectDataService: IProjectDataService
239+
) {
240+
super(
241+
$devicePlatformsConstants,
242+
$errors,
243+
$injector,
244+
$options,
245+
$platformValidationService,
246+
$projectDataService
247+
);
248+
}
249+
}
250+
251+
injector.registerCommand("run|tvos", RunTvOSCommand);

lib/common/definitions/mobile.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,7 @@ declare global {
11061106
isAndroidPlatform(platform: string): boolean;
11071107
isiOSPlatform(platform: string): boolean;
11081108
isvisionOSPlatform(platform: string): boolean;
1109+
istvOSPlatform(platform: string): boolean;
11091110
isApplePlatform(platform: string): boolean;
11101111
normalizePlatformName(platform: string): string;
11111112
validatePlatformName(platform: string): string;
@@ -1150,10 +1151,12 @@ declare global {
11501151
iOS: string;
11511152
Android: string;
11521153
visionOS: string;
1154+
tvOS: string;
11531155

11541156
isiOS(value: string): boolean;
11551157
isAndroid(value: string): boolean;
11561158
isvisionOS(value: string): boolean;
1159+
istvOS(value: string): boolean;
11571160
}
11581161

11591162
interface IDeviceApplication {

lib/common/mobile/device-platforms-constants.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export class DevicePlatformsConstants
66
public iOS = "iOS";
77
public Android = "Android";
88
public visionOS = "visionOS";
9+
public tvOS = "tvOS";
910

1011
public isiOS(value: string) {
1112
return value.toLowerCase() === this.iOS.toLowerCase();
@@ -18,5 +19,9 @@ export class DevicePlatformsConstants
1819
public isvisionOS(value: string) {
1920
return value.toLowerCase() === this.visionOS.toLowerCase();
2021
}
22+
23+
public istvOS(value: string) {
24+
return value.toLowerCase() === this.tvOS.toLowerCase();
25+
}
2126
}
2227
injector.register("devicePlatformsConstants", DevicePlatformsConstants);

lib/common/mobile/ios/device/ios-device.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ export class IOSDevice extends IOSDeviceBase {
159159
} else if (_.startsWith(productType, "realitydevice")) {
160160
// visionos
161161
isArm64Architecture = true;
162+
} else if (_.startsWith(productType, "appletv")) {
163+
// tvos (Apple TV HD and later are arm64)
164+
isArm64Architecture = true;
162165
}
163166

164167
activeArchitecture = isArm64Architecture ? "arm64" : "armv7";
@@ -173,6 +176,10 @@ export class IOSDevice extends IOSDeviceBase {
173176
// visionos
174177
return this.$devicePlatformsConstants.visionOS;
175178
}
179+
if (_.startsWith(productType, "appletv")) {
180+
// tvos
181+
return this.$devicePlatformsConstants.tvOS;
182+
}
176183
return this.$devicePlatformsConstants.iOS;
177184
}
178185
}

lib/common/mobile/ios/simulator/ios-emulator-services.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ class IosEmulatorServices implements Mobile.IiOSSimulatorService {
2424

2525
try {
2626
if (
27-
options.platform === this.$devicePlatformsConstants.visionOS &&
27+
(options.platform === this.$devicePlatformsConstants.visionOS ||
28+
options.platform === this.$devicePlatformsConstants.tvOS) &&
2829
!options.emulatorIdOrName
2930
) {
30-
// find first available visionOS simulator (for now).
31+
// find first available visionOS / tvOS simulator (for now).
3132
const { devices } = await this.tryGetiOSSimDevices();
3233
options.emulatorIdOrName = devices.find(
33-
(device) =>
34-
device.platform === this.$devicePlatformsConstants.visionOS
34+
(device) => device.platform === options.platform
3535
)?.id;
3636
}
3737

lib/common/mobile/log-filter.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ export class LogFilter implements Mobile.ILogFilter {
4444
platform.toLowerCase() ===
4545
this.$devicePlatformsConstants.iOS.toLowerCase() ||
4646
platform.toLowerCase() ===
47-
this.$devicePlatformsConstants.visionOS.toLowerCase()
47+
this.$devicePlatformsConstants.visionOS.toLowerCase() ||
48+
platform.toLowerCase() ===
49+
this.$devicePlatformsConstants.tvOS.toLowerCase()
4850
) {
4951
return this.$injector.resolve("iOSLogFilter");
5052
} else if (

lib/common/mobile/mobile-core/devices-service.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -831,15 +831,14 @@ export class DevicesService
831831
}
832832
}
833833

834-
// make sure if the target platform is visionOS we don't try to run it on an already running iOS simulator...
834+
// make sure if the target platform is visionOS or tvOS we don't try to run it on an already running iOS simulator...
835835
if (
836-
data.platform === this.$devicePlatformsConstants.visionOS &&
836+
(data.platform === this.$devicePlatformsConstants.visionOS ||
837+
data.platform === this.$devicePlatformsConstants.tvOS) &&
837838
deviceInstances.length
838839
) {
839840
const runningDeviceInstance = deviceInstances.find(
840-
(device) =>
841-
device.deviceInfo.platform ===
842-
this.$devicePlatformsConstants.visionOS,
841+
(device) => device.deviceInfo.platform === data.platform,
843842
);
844843
if (!runningDeviceInstance) {
845844
return this.startEmulatorCore(data);

lib/common/mobile/mobile-core/ios-device-discovery.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ export class IOSDeviceDiscovery extends DeviceDiscovery {
2828
return;
2929
}
3030

31-
if (this.$mobileHelper.isvisionOSPlatform(options.platform)) {
31+
if (
32+
this.$mobileHelper.isvisionOSPlatform(options.platform) ||
33+
this.$mobileHelper.istvOSPlatform(options.platform)
34+
) {
3235
// look for ios devices - same logic.
3336
options.platform = this.$devicePlatformsConstants.iOS;
3437
}

0 commit comments

Comments
 (0)