Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 44 additions & 15 deletions Xamarin.MacDev/ManifestExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,21 +218,28 @@ public static IPhoneDeviceType GetUIDeviceFamily (this PDictionary dict)
return GetUIDeviceFamily (dict, ManifestKeys.UIDeviceFamily);
}

static AppleDeviceFamily ParseDeviceFamilyFromNumber (PNumber number)
static bool TryParseDeviceFamilyFromNumber (PNumber number, out AppleDeviceFamily family)
{
switch (number.Value) {
case 1:
return AppleDeviceFamily.IPhone;
family = AppleDeviceFamily.IPhone;
return true;
case 2:
return AppleDeviceFamily.IPad;
family = AppleDeviceFamily.IPad;
return true;
case 3:
return AppleDeviceFamily.TV;
family = AppleDeviceFamily.TV;
return true;
case 4:
return AppleDeviceFamily.Watch;
family = AppleDeviceFamily.Watch;
return true;
case 6:
return AppleDeviceFamily.MacCatalystOptimizedForMac;
family = AppleDeviceFamily.MacCatalystOptimizedForMac;
return true;
default:
throw new ArgumentOutOfRangeException (string.Format ("Unknown device family: {0}", number.Value));
LoggingService.LogWarning ($"Ignoring unrecognized device family number: {number.Value}");
family = default;
return false;
}
}

Expand Down Expand Up @@ -278,11 +285,12 @@ public static IPhoneDeviceType GetUIDeviceFamily (this PDictionary dict, string
val |= ParseDeviceTypeFromString (p);

var number = element as PNumber;
if (number != null)
val |= ParseDeviceFamilyFromNumber (number).ToDeviceType ();
if (number != null && TryParseDeviceFamilyFromNumber (number, out var family))
val |= family.ToDeviceType ();
}
} else if (value is PNumber) {
val |= ParseDeviceFamilyFromNumber ((PNumber) value).ToDeviceType ();
if (TryParseDeviceFamilyFromNumber ((PNumber) value, out var family))
val |= family.ToDeviceType ();
} else if (value is PString) {
val |= ParseDeviceTypeFromString ((PString) value);
}
Expand Down Expand Up @@ -496,6 +504,23 @@ static PDictionary GetNSExtensionAttributes (this PDictionary dict)
return extAtt;
}

static PDictionary GetOrCreateNSExtensionAttributes (this PDictionary dict)
{
var ext = dict.Get<PDictionary> ("NSExtension");
if (ext == null) {
ext = new PDictionary ();
dict ["NSExtension"] = ext;
}

var extAtt = ext.Get<PDictionary> ("NSExtensionAttributes");
if (extAtt == null) {
extAtt = new PDictionary ();
ext ["NSExtensionAttributes"] = extAtt;
}

return extAtt;
}

#endregion

#region Watch App Manifest Keys
Expand All @@ -513,19 +538,23 @@ public static void SetWKWatchKitApp (this PDictionary dict, bool value)
public static string GetWKAppBundleIdentifier (this PDictionary dict)
{
var extAtt = GetNSExtensionAttributes (dict);
if (extAtt == null)
return null;

var str = extAtt.Get<PString> (ManifestKeys.WKAppBundleIdentifier);
return str == null ? null : str.Value;
}

public static void SetWKAppBundleIdentifier (this PDictionary dict, string value)
{
var extAtt = GetNSExtensionAttributes (dict);

if (string.IsNullOrEmpty (value))
extAtt.Remove (ManifestKeys.WKAppBundleIdentifier);
else
if (string.IsNullOrEmpty (value)) {
var extAtt = GetNSExtensionAttributes (dict);
if (extAtt != null)
extAtt.Remove (ManifestKeys.WKAppBundleIdentifier);
} else {
var extAtt = GetOrCreateNSExtensionAttributes (dict);
extAtt [ManifestKeys.WKAppBundleIdentifier] = value;
}
}

public static string GetWKCompanionAppBundleIdentifier (this PDictionary dict)
Expand Down
100 changes: 100 additions & 0 deletions tests/ManifestExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#nullable enable

using NUnit.Framework;
using Xamarin.MacDev;

namespace tests {

[TestFixture]
public class ManifestExtensionsTests {

[Test]
public void GetWKAppBundleIdentifier_ReturnsNull_WhenNSExtensionMissing ()
{
var dict = new PDictionary ();
var result = dict.GetWKAppBundleIdentifier ();
Assert.That (result, Is.Null);
}

[Test]
public void GetWKAppBundleIdentifier_ReturnsNull_WhenNSExtensionAttributesMissing ()
{
var dict = new PDictionary ();
dict.Add ("NSExtension", new PDictionary ());
var result = dict.GetWKAppBundleIdentifier ();
Assert.That (result, Is.Null);
}

[Test]
public void GetWKAppBundleIdentifier_ReturnsValue_WhenPresent ()
{
var dict = new PDictionary ();
var ext = new PDictionary ();
var extAttr = new PDictionary ();
extAttr.Add ("WKAppBundleIdentifier", new PString ("com.test.watchapp"));
ext.Add ("NSExtensionAttributes", extAttr);
dict.Add ("NSExtension", ext);

var result = dict.GetWKAppBundleIdentifier ();
Assert.That (result, Is.EqualTo ("com.test.watchapp"));
}

[Test]
public void SetWKAppBundleIdentifier_CreatesStructure_WhenNSExtensionMissing ()
{
var dict = new PDictionary ();
dict.SetWKAppBundleIdentifier ("com.test.app");
Assert.That (dict.GetWKAppBundleIdentifier (), Is.EqualTo ("com.test.app"));
}

[Test]
public void SetWKAppBundleIdentifier_RemoveIsNoOp_WhenNSExtensionMissing ()
{
var dict = new PDictionary ();
Assert.DoesNotThrow (() => dict.SetWKAppBundleIdentifier (""));
}

[Test]
public void GetUIDeviceFamily_SkipsUnknownDeviceFamilyNumber ()
{
var dict = new PDictionary ();
var arr = new PArray ();
arr.Add (new PNumber (99));
dict.Add ("UIDeviceFamily", arr);

var result = dict.GetUIDeviceFamily ("UIDeviceFamily");
Assert.That (result, Is.EqualTo (IPhoneDeviceType.NotSet));
}

[Test]
public void GetUIDeviceFamily_MixedKnownAndUnknown_SkipsUnknown ()
{
var dict = new PDictionary ();
var arr = new PArray ();
arr.Add (new PNumber (2)); // IPad
arr.Add (new PNumber (99)); // unknown — should be skipped
dict.Add ("UIDeviceFamily", arr);

var result = dict.GetUIDeviceFamily ("UIDeviceFamily");
Assert.That (result.HasFlag (IPhoneDeviceType.IPad), Is.True);
Assert.That (result.HasFlag (IPhoneDeviceType.IPhone), Is.False);
}

[Test]
public void GetUIDeviceFamily_ParsesKnownDeviceFamilies ()
{
var dict = new PDictionary ();
var arr = new PArray ();
arr.Add (new PNumber (1));
arr.Add (new PNumber (2));
dict.Add ("UIDeviceFamily", arr);

var result = dict.GetUIDeviceFamily ("UIDeviceFamily");
Assert.That (result.HasFlag (IPhoneDeviceType.IPhone), Is.True);
Assert.That (result.HasFlag (IPhoneDeviceType.IPad), Is.True);
}
}
}
Loading