diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2a6cfeb..516e2d9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,10 +14,10 @@ jobs: - name: GitHub Action for SwiftLint uses: norio-nomura/action-swiftlint@3.2.1 test: - runs-on: macos-latest + runs-on: macos-13 steps: - name: Xcode Setup - uses: maxim-lobanov/setup-xcode@v1 + uses: maxim-lobanov/setup-xcode@v1.6.0 with: xcode-version: latest-stable - name: Checkout project diff --git a/Images/Popup/slideshow_1.png b/Images/Popup/slideshow_1.png new file mode 100644 index 0000000..4a5ba2d Binary files /dev/null and b/Images/Popup/slideshow_1.png differ diff --git a/Notification Agent Alert Tests/NAATriggersTests.swift b/Notification Agent Alert Tests/NAATriggersTests.swift index e1a135a..027876b 100644 --- a/Notification Agent Alert Tests/NAATriggersTests.swift +++ b/Notification Agent Alert Tests/NAATriggersTests.swift @@ -3,7 +3,7 @@ // Notification Agent Alert Tests // // Created by Simone Martorelli on 01/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Alerts/AppDelegate.swift b/Notification Agent Alerts/AppDelegate.swift index 96b30e0..294b4e3 100644 --- a/Notification Agent Alerts/AppDelegate.swift +++ b/Notification Agent Alerts/AppDelegate.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 18/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Alerts/Extensions/NotificationDispatch-Extension.swift b/Notification Agent Alerts/Extensions/NotificationDispatch-Extension.swift index 6cadf0a..ed96abd 100644 --- a/Notification Agent Alerts/Extensions/NotificationDispatch-Extension.swift +++ b/Notification Agent Alerts/Extensions/NotificationDispatch-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 5/27/21. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Banner Tests/NABTriggersTests.swift b/Notification Agent Banner Tests/NABTriggersTests.swift index 0ebeba6..1201421 100644 --- a/Notification Agent Banner Tests/NABTriggersTests.swift +++ b/Notification Agent Banner Tests/NABTriggersTests.swift @@ -3,7 +3,7 @@ // Notification Agent Alert Tests // // Created by Simone Martorelli on 01/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Banners/AppDelegate.swift b/Notification Agent Banners/AppDelegate.swift index 902807d..f3b238a 100644 --- a/Notification Agent Banners/AppDelegate.swift +++ b/Notification Agent Banners/AppDelegate.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Jan Valentik on 18/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Banners/Extensions/NotificationDispatch-Extension.swift b/Notification Agent Banners/Extensions/NotificationDispatch-Extension.swift index 6cadf0a..ed96abd 100644 --- a/Notification Agent Banners/Extensions/NotificationDispatch-Extension.swift +++ b/Notification Agent Banners/Extensions/NotificationDispatch-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 5/27/21. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Core Tests/NACInteractiveEFCLControllerTests.swift b/Notification Agent Core Tests/NACInteractiveEFCLControllerTests.swift index a618a1f..aaba0eb 100644 --- a/Notification Agent Core Tests/NACInteractiveEFCLControllerTests.swift +++ b/Notification Agent Core Tests/NACInteractiveEFCLControllerTests.swift @@ -3,7 +3,7 @@ // Notification Agent Core Tests // // Created by Simone Martorelli on 27/05/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Core Tests/NACTriggersTests.swift b/Notification Agent Core Tests/NACTriggersTests.swift index fa4c369..a5d6d0e 100644 --- a/Notification Agent Core Tests/NACTriggersTests.swift +++ b/Notification Agent Core Tests/NACTriggersTests.swift @@ -3,7 +3,7 @@ // Notification Agent Core Tests // // Created by Simone Martorelli on 26/05/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Core/AppDelegate.swift b/Notification Agent Core/AppDelegate.swift index b8ab875..2b6ff56 100644 --- a/Notification Agent Core/AppDelegate.swift +++ b/Notification Agent Core/AppDelegate.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Jan Valentik on 18/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Core/Controllers/Context.swift b/Notification Agent Core/Controllers/Context.swift index d58e21a..9bf3419 100644 --- a/Notification Agent Core/Controllers/Context.swift +++ b/Notification Agent Core/Controllers/Context.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 31/03/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Core/Controllers/DeepLinkEngine.swift b/Notification Agent Core/Controllers/DeepLinkEngine.swift index 2949c42..93fb640 100644 --- a/Notification Agent Core/Controllers/DeepLinkEngine.swift +++ b/Notification Agent Core/Controllers/DeepLinkEngine.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 6/22/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Core/Controllers/HelpBuilder.swift b/Notification Agent Core/Controllers/HelpBuilder.swift index 80a26b7..0a8d1f4 100644 --- a/Notification Agent Core/Controllers/HelpBuilder.swift +++ b/Notification Agent Core/Controllers/HelpBuilder.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 8/27/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // // swiftlint:disable type_body_length file_length @@ -45,7 +45,9 @@ public final class HelpBuilder { "-popup_reminder".yellow(), "-retain_values".yellow(), "-background_panel".yellow(), - "-unmovable".yellow()] + "-unmovable".yellow(), + "-disable_quit".yellow(), + "-custom_width".yellow()] static let bannerArguments: [String] = ["-type".green(), "-title".yellow(), "-subtitle".yellow(), @@ -65,7 +67,8 @@ public final class HelpBuilder { "-hide_title_bar_buttons".yellow(), "-background_panel".yellow(), "-unmovable".yellow(), - "-timeout".yellow()] + "-timeout".yellow(), + "-disable_quit".yellow()] static let systemAlertArguments: [String] = ["-type".green(), "-title".yellow(), "-subtitle".yellow(), @@ -89,22 +92,24 @@ public final class HelpBuilder { "\n The custom icon path/URL/SF Symbol name defined for this notification.\n Example: -icon_path \"~/Icon/Path.png\"", "\n The custom icon width defined for this notification. Max. width = 150\n Example: -icon_width \"150\"", "\n The custom icon height defined for this notification. Max. height = 300\n Example: -icon_height \"150\"", - "[ whitebox | timer | image | video | progressbar | input | secureinput | dropdown | html | htmlwhitebox | checklist | datepicker ]".red() + "\n The UI type for the needed accessory view.\n Example: -accessory_view_type whitebox", + "[ whitebox | timer | image | video | progressbar | input | secureinput | dropdown | html | htmlwhitebox | checklist | datepicker | slideshow ]".red() + "\n The UI type for the needed accessory view.\n Example: -accessory_view_type whitebox", "\n The payload for the accessory view:\n " + "- Text for " + "[ whitebox ]".red() + " view type;\n " + "- Text for " + "[ timer ]".red() + " view type. This will be timer's label. Use \"%@\" to define timer's position inside the label. Use " + "[ -timeout ]".yellow() + " argument to define timer's duration;\n " + - "- File path/link for " + "[ image ]".red() + " view type;\n " + + "- File path/link or base64 encoded string for " + "[ image ]".red() + " view type;\n " + "- Text with the format " + "\"/url TEXT /autoplay /delay INT\" ".green() + "for " + "[ video ]".red() + " view type;\n " + "- Text with the format " + "\"/percent DOUBLE /top_message TEXT /bottom_message TEXT /user_interaction_enabled BOOL /user_interruption_allowed BOOL\" ".green() + "for " + "[ progressbar ]".red() + " view type;\n " + "- Text with the format " + "\"/placeholder TEXT /title TEXT /value TEXT /required\" ".green() + "for the " + "[ input | secureinput ]".red() + " view type;\n " + "- Text with the format " + "\"/list ITEM\\nITEM\\nITEM /selected INT /placeholder TEXT /title TEXT\" ".green() + "for " + "[ dropdown ]".red() + " view type;\n " + "- Text with HTML format for " + "[ html | htmlwhitebox ]".red() + " view type;\n " + "- Text with the format " + "\"/list ITEM\\nITEM\\nITEM /preselection ITEM_INDEX ITEM_INDEX ITEM_INDEX /required /complete /title TEXT /radio\" ".green() + "for " + "[ checklist ]".red() + " view type. To read more about the usage of /complete and /required look at the project wiki;\n " + - "- Text with the format " + "\"/title TEXT /preselection DATE WITH FORMAT yyyy-MM-dd hh:mm:ss /style TEXT /components TEXT\" ".green() + "for " + "[ datepicker ]".red() + " view type. To read more about the usage of /style and /components look at the project wiki;\n " + + "- Text with the format " + "\"/title TEXT /preselection DATE WITH FORMAT yyyy-MM-dd hh:mm:ss /start_date DATE WITH FORMAT yyyy-MM-dd hh:mm:ss /end_date DATE WITH FORMAT yyyy-MM-dd hh:mm:ss /style TEXT /components TEXT\" ".green() + "for " + "[ datepicker ]".red() + " view type. To read more about the usage of /style and /components look at the project wiki;\n " + + "- Text with the format " + "\"/images URL\\nURL\\nURL /autoplay /delay INT\" ".green() + "for " + "[ slideshow ]".red() + " view type;\n " + "Example 1: -accessory_view_payload \"This is the time left: %@\"\n " + "Example 2: -accessory_view_payload \"/percent 0 /top_message This is the top message /bottom_message This is the bottom message\";\n " + "Example 3: -accessory_view_payload \"/percent indeterminate /top_message This is the top message /bottom_message This is the bottom message\";\n " + - "Example 4: -accessory_view_payload \"

Hello, world!

this is a line of text

this is a code block
this is the second line of a code block

this is red text\".", + "Example 4: -accessory_view_payload \"

Hello, world!

this is a line of text

this is a code block
this is the second line of a code block

this is red text\"\n " + + "Example 5: -accessory_view_payload \"/images /path/to/image.jpg\\nhttps://www.url.to/image.png\\nhttps://www.url.to/image.png /autoplay /delay 3\".", "\n Same as for accessory_view_type argument.", "\n Same as for accessory_view_payload argument.", "\n The label of the main button.\n Example: -main_button_label \"Main button title\"", @@ -130,8 +135,10 @@ public final class HelpBuilder { "\n A text payload to define the behavior of an optional reminder for the pop-up. The reminder is basically a timer at the end of which the pop-up is pushed again on top of the view hierarchy on screen. The payload format is: " + "\"/timeinterval /silent /repeat\" ".green() + "\n Example: -popup_reminder \"/timeinterval 300\"", "\n Flag that tells the agent to print the available accessory view outputs on any exit (main or secondary button clicked).", "[ opaque | translucent ]".red() + "\n The style for the background panel that will cover all the screens.\n Example: -background_panel opaque", - "\n Flag that make the UI unmovable for the user.\n Example: -unmovable"] - + "\n Flag that make the UI unmovable for the user.\n Example: -unmovable", + "\n Flag that tells the agent to ignore cmd+q shortcut.\n Example: -disable_quit", + "\n A custom width for the UI.\n Example: -custom_width 1000", + "\n Flag that tells the agent to not show any destructive CTA (Button).\n Example: -buttonless"] static let bannerDescriptions: [String] = ["[ banner | alert ]".red() + "\n The UI type of the notification.\n Example: -type banner", "\n The title of the notification.\n Example: -title \"Title\"", "\n The subtitle of the notification. It supports MarkDown text.\n Example: -subtitle \"Subtitle\"", @@ -151,7 +158,8 @@ public final class HelpBuilder { "\n Flag that tells the agent to remove the title bar buttons for the Onbording UI.\n Example: -hide_title_bar_buttons", "[ opaque | translucent ]".red() + "\n The style for the background panel that will cover all the screens.\n Example: -background_panel opaque", "\n Flag that make the UI unmovable for the user.\n Example: -unmovable", - "\n The timeout for the onboarding. After this amount of seconds the agent exit with the timeout exit code.\n Example: -timeout 300"] + "\n The timeout for the onboarding. After this amount of seconds the agent exit with the timeout exit code.\n Example: -timeout 300", + "\n Flag that tells the agent to ignore cmd+q shortcut.\n Example: -disable_quit"] static let systemAlertDescriptions: [String] = ["[ systemAlert ]".red() + "\n The UI type of the notification.\n Example: -type systemAlert", "\n The title of the notification.\n Example: -title \"Title\"", "\n The subtitle of the notification.\n Example: -subtitle \"Subtitle\"", @@ -205,6 +213,7 @@ public final class HelpBuilder { "4".bold(), "200".bold(), "201".bold(), + "239".bold(), "250".bold(), "255".bold(), "260".bold()] @@ -215,6 +224,7 @@ public final class HelpBuilder { "Timeout.", "Untracked success.", "Received SigInt.", + "User dimissed the popup.", "Invalid number of arguments.", "Invalid arguments syntax.", "Unable to load resources"] diff --git a/Notification Agent Core/Controllers/NALogger.swift b/Notification Agent Core/Controllers/NALogger.swift index a4d9272..c799f5f 100644 --- a/Notification Agent Core/Controllers/NALogger.swift +++ b/Notification Agent Core/Controllers/NALogger.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 8/27/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Core/Controllers/TaskManager.swift b/Notification Agent Core/Controllers/TaskManager.swift index 44b240a..25cdb06 100644 --- a/Notification Agent Core/Controllers/TaskManager.swift +++ b/Notification Agent Core/Controllers/TaskManager.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 16/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Core/Extensions/EFCLController-Extension.swift b/Notification Agent Core/Extensions/EFCLController-Extension.swift index 2d982ba..ee2f3df 100644 --- a/Notification Agent Core/Extensions/EFCLController-Extension.swift +++ b/Notification Agent Core/Extensions/EFCLController-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent Banner // // Created by Simone Martorelli on 28/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -194,28 +194,28 @@ extension EFCLController { private func buildDict(from keys: [String], and values: [String]) throws -> [String: Any] { var checkedValues = values + var checkedKeys = keys guard !keys.isEmpty && !values.isEmpty else { HelpBuilder.printNoArgumentsPage() throw NAError.efclController(type: .invalidArgumentsSyntax) } for arg in Self.standaloneBooleanArguments { - guard let index = keys.firstIndex(where: { $0 == arg }) else { continue } - if index > checkedValues.count { - checkedValues.append("true") - } else { - checkedValues.insert("true", at: index) - } + guard let index = checkedKeys.firstIndex(where: { $0 == arg }) else { continue } + let standAloneArgument = checkedKeys[index] + checkedKeys.remove(at: index) + checkedKeys.append(standAloneArgument) + checkedValues.append("true") } - guard keys.count == checkedValues.count else { + guard checkedKeys.count == checkedValues.count else { throw NAError.efclController(type: .invalidArgumentsFormat) } var dict: [String: Any] = [:] - for index in keys.indices { - dict[keys[index]] = checkedValues[index] + for index in checkedKeys.indices { + dict[checkedKeys[index]] = checkedValues[index] } return dict } - + /// Try to create a NotificationObject from the passed dictionary. /// - Parameter dict: the passed dictionary. /// - Throws: NAError. diff --git a/Notification Agent Core/Extensions/NotificationDispatch-Extension.swift b/Notification Agent Core/Extensions/NotificationDispatch-Extension.swift index 123bde2..6739900 100644 --- a/Notification Agent Core/Extensions/NotificationDispatch-Extension.swift +++ b/Notification Agent Core/Extensions/NotificationDispatch-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 28/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Onboarding Tests/NAOTriggersTests.swift b/Notification Agent Onboarding Tests/NAOTriggersTests.swift index 8b79125..db053e4 100644 --- a/Notification Agent Onboarding Tests/NAOTriggersTests.swift +++ b/Notification Agent Onboarding Tests/NAOTriggersTests.swift @@ -3,7 +3,7 @@ // Notification Agent Onboarding Tests // // Created by Simone Martorelli on 01/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Onboarding UI Tests/NAOUITests.swift b/Notification Agent Onboarding UI Tests/NAOUITests.swift index add6dfc..5241646 100644 --- a/Notification Agent Onboarding UI Tests/NAOUITests.swift +++ b/Notification Agent Onboarding UI Tests/NAOUITests.swift @@ -3,7 +3,7 @@ // Notification Agent Onboarding UI Tests // // Created by Simone Martorelli on 08/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -12,36 +12,82 @@ import XCTest class NAOUITests: XCTestCase { /// Testing simple Onboarding UI - func test1Onboarding() throws { - let useCase = "eyJub3RpZmljYXRpb24iOnsidG9waWNJRCI6InVudHJhY2tlZCIsIm1haW5CdXR0b24iOnsibGFiZWwiOiJPSyIsImNhbGxUb0FjdGlvblR5cGUiOiJub25lIiwiY2FsbFRvQWN0aW9uUGF5bG9hZCI6IiJ9LCJub3RpZmljYXRpb25JRCI6InVudHJhY2tlZCIsInJldGFpblZhbHVlcyI6ZmFsc2UsImFjY2Vzc29yeVZpZXdzIjpbXSwicGF5bG9hZCI6eyJwYWdlcyI6W3siYm9keSI6IkZpcnN0IHBhZ2UncyBib2R5IiwidG9wSWNvbiI6InNxdWFyZS5hbmQuYXJyb3cudXAiLCJ0aXRsZSI6IkZpcnN0IHBhZ2UncyB0aXRsZSIsInN1YnRpdGxlIjoiRmlyc3QgcGFnZSdzIHN1YnRpdGxlIiwiaW5mb1NlY3Rpb24iOnsiZmllbGRzIjpbeyJpZCI6IlNvbWUgRGVzY3JpcHRpb24gU29tZSIsImxhYmVsIjoiU29tZSBEZXNjcmlwdGlvbiBTb21lIn0seyJpZCI6IlNvbWUgRGVzY3JpcHRpb24gU29tZSIsImxhYmVsIjoiU29tZSBEZXNjcmlwdGlvbiBTb21lIn0seyJpZCI6IlNvbWUgRGVzY3JpcHRpb24gU29tZSIsImxhYmVsIjoiU29tZSBEZXNjcmlwdGlvbiBTb21lIn1dfX0seyJzdWJ0aXRsZSI6IlNlY29uZCBwYWdlJ3Mgc3VidGl0bGUiLCJzaW5nbGVDaGFuZ2UiOnRydWUsInByaW1hcnlCdXR0b25MYWJlbCI6IlNvbWUiLCJ0aXRsZSI6IlNlY29uZCBwYWdlJ3MgdGl0bGUiLCJ0ZXJ0aWFyeUJ1dHRvbiI6eyJsYWJlbCI6IlRlcnRpYXJ5IiwiY2FsbFRvQWN0aW9uVHlwZSI6ImxpbmsiLCJjYWxsVG9BY3Rpb25QYXlsb2FkIjoiaHR0cHM6XC9cL3d3dy5nb29nbGUuY29tIn0sImluZm9TZWN0aW9uIjp7ImZpZWxkcyI6W3siaWQiOiJGaXJzdCBsYWJlbCBvbmx5IiwibGFiZWwiOiJGaXJzdCBsYWJlbCBvbmx5In0seyJpZCI6IlNlY29uZCBsYWJlbCBvbmx5IiwibGFiZWwiOiJTZWNvbmQgbGFiZWwgb25seSJ9LHsiaWQiOiJUaGlyZCBsYWJlbCBvbmx5IiwibGFiZWwiOiJUaGlyZCBsYWJlbCBvbmx5In1dfSwiYm9keSI6IlNlY29uZCBwYWdlJ3MgYm9keSJ9LHsiYm9keSI6IlRoaXJkIHBhZ2UncyBib2R5IiwidGl0bGUiOiJUaGlyZCBwYWdlJ3MgdGl0bGUiLCJzdWJ0aXRsZSI6IlRoaXJkIHBhZ2UncyBzdWJ0aXRsZSIsInNpbmdsZUNoYW5nZSI6dHJ1ZX0seyJ0aXRsZSI6IkZvdXJ0aCBwYWdlJ3MgdGl0bGUiLCJzdWJ0aXRsZSI6IkZvdXJ0aCBwYWdlJ3Mgc3VidGl0bGUiLCJib2R5IjoiRm91cnRoIHBhZ2UncyBib2R5In1dLCJwcm9ncmVzc0JhclBheWxvYWQiOiJhdXRvbWF0aWMifSwiaXNNb3ZhYmxlIjp0cnVlLCJhbHdheXNPblRvcCI6ZmFsc2UsInR5cGUiOiJvbmJvYXJkaW5nIiwic2lsZW50IjpmYWxzZSwic2hvd1N1cHByZXNzaW9uQnV0dG9uIjpmYWxzZSwibWluaWF0dXJpemFibGUiOmZhbHNlLCJiYXJUaXRsZSI6Ik1hY0BJQk0gTm90aWZpY2F0aW9ucyIsImZvcmNlTGlnaHRNb2RlIjpmYWxzZSwiaGlkZVRpdGxlQmFyQnV0dG9ucyI6ZmFsc2V9LCJzZXR0aW5ncyI6eyJpc1ZlcmJvc2VNb2RlRW5hYmxlZCI6ZmFsc2UsImVudmlyb25tZW50IjoicHJvZCJ9fQ==" // pragma: allowlist-secret - let app = XCUIApplication() - app.launchArguments = [useCase] - app.launch() - XCTAssert(app.staticTexts["onboarding_title"].exists) - XCTAssert(app.staticTexts["onboarding_subtitle"].exists) - XCTAssert(app.staticTexts["onboarding_body"].exists) - XCTAssert(app.buttons["main_button"].exists) - XCTAssert(!app.buttons["secondary_button"].exists) - XCTAssert(app.buttons["help_button"].exists) - app.buttons["main_button"].tap() - XCTAssert(app.staticTexts["onboarding_title"].exists) - XCTAssert(app.staticTexts["onboarding_subtitle"].exists) - XCTAssert(app.staticTexts["onboarding_body"].exists) - XCTAssert(app.buttons["main_button"].exists) - XCTAssert(app.buttons["secondary_button"].exists) - XCTAssert(app.buttons["tertiary_button"].exists) - XCTAssert(app.buttons["help_button"].exists) - app.buttons["main_button"].tap() - XCTAssert(app.staticTexts["onboarding_title"].exists) - XCTAssert(app.staticTexts["onboarding_subtitle"].exists) - XCTAssert(app.staticTexts["onboarding_body"].exists) - XCTAssert(app.buttons["main_button"].exists) - XCTAssert(!app.buttons["secondary_button"].exists) - app.buttons["main_button"].tap() - XCTAssert(app.staticTexts["onboarding_title"].exists) - XCTAssert(app.staticTexts["onboarding_subtitle"].exists) - XCTAssert(app.staticTexts["onboarding_body"].exists) - XCTAssert(app.buttons["main_button"].exists) - XCTAssert(!app.buttons["secondary_button"].exists) + func testA1Onboarding() throws { + let useCase = """ +{"notification":{"retainValues":false,"isMovable":true,"type":"onboarding","mainButton":{"label":"OK","callToActionType":"none","callToActionPayload":""},"barTitle":"IBM Notifier","alwaysOnTop":false,"showSuppressionButton":false,"hideTitleBarButtons":false,"accessoryViews":[],"payload":{"pages":[{"infoSection":{"fields":[{"id":"BE8ACDC6-1159-421E-8ECA-F84B6B6785ED","label":"Some Description Some"},{"id":"4C045585-72C2-428B-B574-F55CF86E5DCA","label":"Some Description Some"},{"id":"EF546A45-64CA-473D-8BEA-4BF18C3D624F","label":"Some Description Some"}]},"topIcon":"square.and.arrow.up","subtitle":"First page's subtitle","title":"First page's title","body":"First page's body"},{"singleChange":true,"infoSection":{"fields":[{"label":"First label only","id":"031F8516-F122-4A7D-A53C-4F41C9A6C86A"},{"id":"9A2DE192-E512-484E-B42B-2215C84A0B97","label":"Second label only"},{"label":"Third label only","id":"B9F441F5-E55D-4C71-B0BC-53347A4CE6A4"}]},"tertiaryButton":{"callToActionPayload":"https:\\/\\/www.google.com","label":"Tertiary","callToActionType":"link"},"title":"Second page's title","body":"Second page's body","primaryButtonLabel":"Some","subtitle":"Second page's subtitle"},{"title":"Third page's title","body":"Third page's body","singleChange":true,"subtitle":"Third page's subtitle"},{"body":"Fourth page's body","subtitle":"Fourth page's subtitle","title":"Fourth page's title"}],"progressBarPayload":"automatic"},"silent":false,"forceLightMode":false,"disableQuit":false,"buttonless":false,"miniaturizable":false,"topicID":"untracked","notificationID":"untracked"},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} +""" // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.staticTexts["onboarding_title"].exists) + XCTAssert(app.staticTexts["onboarding_subtitle"].exists) + XCTAssert(app.staticTexts["onboarding_body"].exists) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(!app.buttons["secondary_button"].exists) + XCTAssert(app.buttons["help_button"].exists) + app.buttons["main_button"].tap() + XCTAssert(app.staticTexts["onboarding_title"].exists) + XCTAssert(app.staticTexts["onboarding_subtitle"].exists) + XCTAssert(app.staticTexts["onboarding_body"].exists) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.buttons["tertiary_button"].exists) + XCTAssert(app.buttons["help_button"].exists) + app.buttons["main_button"].tap() + XCTAssert(app.staticTexts["onboarding_title"].exists) + XCTAssert(app.staticTexts["onboarding_subtitle"].exists) + XCTAssert(app.staticTexts["onboarding_body"].exists) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(!app.buttons["secondary_button"].exists) + app.buttons["main_button"].tap() + XCTAssert(app.staticTexts["onboarding_title"].exists) + XCTAssert(app.staticTexts["onboarding_subtitle"].exists) + XCTAssert(app.staticTexts["onboarding_body"].exists) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(!app.buttons["secondary_button"].exists) + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing simple Onboarding UI with accessory views. + func testA2Onboarding() throws { + let useCase = """ +{"notification":{"retainValues":false,"isMovable":true,"type":"onboarding","mainButton":{"label":"OK","callToActionType":"none","callToActionPayload":""},"barTitle":"IBM Notifier","alwaysOnTop":false,"showSuppressionButton":false,"hideTitleBarButtons":false,"accessoryViews":[],"payload":{"pages":[{"accessoryViews":[[{"type":"image","payload":"https://compote.slate.com/images/697b023b-64a5-49a0-8059-27b963453fb1.gif?crop=780%2C520%2Cx0%2Cy0&width=2200"},{"type":"image","payload":"https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg"}]],"infoSection":{"fields":[{"id":"BE8ACDC6-1159-421E-8ECA-F84B6B6785ED","label":"Some Description Some"},{"id":"4C045585-72C2-428B-B574-F55CF86E5DCA","label":"Some Description Some"},{"id":"EF546A45-64CA-473D-8BEA-4BF18C3D624F","label":"Some Description Some"}]},"topIcon":"square.and.arrow.up","subtitle":"First page's subtitle","title":"First page's title","body":"First page's body"},{"singleChange":true,"infoSection":{"fields":[{"label":"First label only","id":"031F8516-F122-4A7D-A53C-4F41C9A6C86A"},{"id":"9A2DE192-E512-484E-B42B-2215C84A0B97","label":"Second label only"},{"label":"Third label only","id":"B9F441F5-E55D-4C71-B0BC-53347A4CE6A4"}]},"tertiaryButton":{"callToActionPayload":"https:\\/\\/www.google.com","label":"Tertiary","callToActionType":"link"},"title":"Second page's title","body":"Second page's body","primaryButtonLabel":"Some","subtitle":"Second page's subtitle"},{"title":"Third page's title","body":"Third page's body","singleChange":true,"subtitle":"Third page's subtitle"},{"body":"Fourth page's body","subtitle":"Fourth page's subtitle","title":"Fourth page's title"}],"progressBarPayload":"automatic"},"silent":false,"forceLightMode":false,"disableQuit":false,"buttonless":false,"miniaturizable":false,"topicID":"untracked","notificationID":"untracked"},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} +""" // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.staticTexts["onboarding_title"].exists) + XCTAssert(app.staticTexts["onboarding_subtitle"].exists) + XCTAssert(app.staticTexts["onboarding_body"].exists) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(!app.buttons["secondary_button"].exists) + XCTAssert(app.buttons["help_button"].exists) + app.buttons["main_button"].tap() + XCTAssert(app.staticTexts["onboarding_title"].exists) + XCTAssert(app.staticTexts["onboarding_subtitle"].exists) + XCTAssert(app.staticTexts["onboarding_body"].exists) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.buttons["tertiary_button"].exists) + XCTAssert(app.buttons["help_button"].exists) + app.buttons["main_button"].tap() + XCTAssert(app.staticTexts["onboarding_title"].exists) + XCTAssert(app.staticTexts["onboarding_subtitle"].exists) + XCTAssert(app.staticTexts["onboarding_body"].exists) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(!app.buttons["secondary_button"].exists) + app.buttons["main_button"].tap() + XCTAssert(app.staticTexts["onboarding_title"].exists) + XCTAssert(app.staticTexts["onboarding_subtitle"].exists) + XCTAssert(app.staticTexts["onboarding_body"].exists) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(!app.buttons["secondary_button"].exists) + } else { + XCTAssert(false, "Failed to encode the usecase.") + } } } diff --git a/Notification Agent Onboarding/AppDelegate.swift b/Notification Agent Onboarding/AppDelegate.swift index 6e2667a..a19e5d2 100644 --- a/Notification Agent Onboarding/AppDelegate.swift +++ b/Notification Agent Onboarding/AppDelegate.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 18/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // @@ -35,6 +35,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { NSEvent.addLocalMonitorForEvents(matching: .keyDown) { event in switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) { case [.command] where event.characters == "q": + guard !self.context.disableQuit else { return .none } Utils.applicationExit(withReason: .userDismissedOnboarding) default: return event diff --git a/Notification Agent Onboarding/Controllers/OnboardingInteractiveEFCLController.swift b/Notification Agent Onboarding/Controllers/OnboardingInteractiveEFCLController.swift index a644714..cbe7590 100644 --- a/Notification Agent Onboarding/Controllers/OnboardingInteractiveEFCLController.swift +++ b/Notification Agent Onboarding/Controllers/OnboardingInteractiveEFCLController.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 24/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Onboarding/Extensions/NotificationDispatch-Extension.swift b/Notification Agent Onboarding/Extensions/NotificationDispatch-Extension.swift index bbefbd9..0d42731 100644 --- a/Notification Agent Onboarding/Extensions/NotificationDispatch-Extension.swift +++ b/Notification Agent Onboarding/Extensions/NotificationDispatch-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 5/27/21. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Onboarding/Views/OnboardingView.swift b/Notification Agent Onboarding/Views/OnboardingView.swift index 21783d6..0635261 100644 --- a/Notification Agent Onboarding/Views/OnboardingView.swift +++ b/Notification Agent Onboarding/Views/OnboardingView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 03/04/2023. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Onboarding/Views/OnboardingViewModel.swift b/Notification Agent Onboarding/Views/OnboardingViewModel.swift index 141acb0..5691428 100644 --- a/Notification Agent Onboarding/Views/OnboardingViewModel.swift +++ b/Notification Agent Onboarding/Views/OnboardingViewModel.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 03/04/2023. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // // swiftlint:disable function_body_length diff --git a/Notification Agent Onboarding/Views/PageView.swift b/Notification Agent Onboarding/Views/PageView.swift index 823212f..5860ad4 100644 --- a/Notification Agent Onboarding/Views/PageView.swift +++ b/Notification Agent Onboarding/Views/PageView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 05/04/2023. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -94,6 +94,7 @@ struct PageView: View { HStack(alignment: .top) { ForEach(row, id: \.hashValue) { accessoryView in accessoryView + .environmentObject(viewModel.viewSpec) } } } diff --git a/Notification Agent Onboarding/Views/PageViewModel.swift b/Notification Agent Onboarding/Views/PageViewModel.swift index 6fce1b9..5a7cebb 100644 --- a/Notification Agent Onboarding/Views/PageViewModel.swift +++ b/Notification Agent Onboarding/Views/PageViewModel.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 26/04/2023. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -19,6 +19,7 @@ final class PageViewModel: ObservableObject { var primaryButtonStates: [[SwiftUIButtonState]] var secondaryButtonStates: [[SwiftUIButtonState]] var accessoryViewsMatrix: [[AccessoryViewWrapper]] + var viewSpec: ViewSpec // MARK: - Binded Variables @@ -39,6 +40,7 @@ final class PageViewModel: ObservableObject { self._outputs = outp self._primaryButtonState = primaryButtonState self._secondaryButtonState = secondaryButtonState + self.viewSpec = ViewSpec(mainViewWidth: 832, contentMode: .fit, iconSize: CGSize(width: 86, height: 86)) primaryButtonStates = [] secondaryButtonStates = [] @@ -72,7 +74,7 @@ final class PageViewModel: ObservableObject { guard newValue != secondaryButtonState else { return } secondaryButtonState = newValue self.evaluateBindings() - }), accessoryView: accessoryView), contentMode: .fit)) + }), accessoryView: accessoryView))) } primaryButtonStates.append(primaryButtonStatesRow) secondaryButtonStates.append(secondaryButtonStatesRow) diff --git a/Notification Agent Popup Tests/NAPTriggersTests.swift b/Notification Agent Popup Tests/NAPTriggersTests.swift index 1af91e9..7a122c2 100644 --- a/Notification Agent Popup Tests/NAPTriggersTests.swift +++ b/Notification Agent Popup Tests/NAPTriggersTests.swift @@ -3,7 +3,7 @@ // Notification Agent Popups Tests // // Created by Simone Martorelli on 01/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Popup UI Tests/NAPUITests.swift b/Notification Agent Popup UI Tests/NAPUITests.swift index 6e918b5..85c71e8 100644 --- a/Notification Agent Popup UI Tests/NAPUITests.swift +++ b/Notification Agent Popup UI Tests/NAPUITests.swift @@ -3,12 +3,13 @@ // Notification Agent Popup UI Tests // // Created by Simone Martorelli on 02/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // import XCTest +// swiftlint:disable type_body_length file_length class NAPUITests: XCTestCase { /// Testing simple Pop-up with: @@ -16,36 +17,48 @@ class NAPUITests: XCTestCase { /// Main Button: Label --> Ok /// BarTitle: Some Title /// Icon: "default_icon" - func test1Popup() throws { - let useCase = "eyJub3RpZmljYXRpb24iOnsidG9waWNJRCI6InVudHJhY2tlZCIsIm1haW5CdXR0b24iOnsibGFiZWwiOiJPSyIsImNhbGxUb0FjdGlvblR5cGUiOiJub25lIiwiY2FsbFRvQWN0aW9uUGF5bG9hZCI6IiJ9LCJoaWRlVGl0bGVCYXJCdXR0b25zIjpmYWxzZSwicmV0YWluVmFsdWVzIjpmYWxzZSwiYWNjZXNzb3J5Vmlld3MiOltdLCJpc01vdmFibGUiOnRydWUsImFsd2F5c09uVG9wIjpmYWxzZSwidHlwZSI6InBvcHVwIiwidGl0bGUiOiJUaGlzIGlzIGEgdGl0bGUiLCJzaWxlbnQiOmZhbHNlLCJzaG93U3VwcHJlc3Npb25CdXR0b24iOmZhbHNlLCJtaW5pYXR1cml6YWJsZSI6ZmFsc2UsImJhclRpdGxlIjoiU29tZSBUaXRsZSIsImZvcmNlTGlnaHRNb2RlIjpmYWxzZSwibm90aWZpY2F0aW9uSUQiOiJ1bnRyYWNrZWQifSwic2V0dGluZ3MiOnsiaXNWZXJib3NlTW9kZUVuYWJsZWQiOmZhbHNlLCJlbnZpcm9ubWVudCI6InByb2QifX0=" // pragma: allowlist-secret - let app = XCUIApplication() - app.launchArguments = [useCase] - app.launch() - - XCTAssert(app.buttons["main_button"].exists) - XCTAssertEqual(app.buttons["main_button"].title, "OK") - XCTAssertEqual(app.images["popup_icon"].label, "default_icon") - XCTAssert(app.staticTexts["popup_title"].exists) - XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") - XCTAssertEqual(app.windows["main_window"].title, "Some Title") - app.terminate() + func testA1Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"OK","callToActionType":"none","callToActionPayload":""},"hideTitleBarButtons":false,"retainValues":false,"accessoryViews":[],"alwaysOnTop":false,"type":"popup","title":"This is a title","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some Title","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "OK") + XCTAssertEqual(app.images["popup_icon"].label, "default_icon") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssertEqual(app.windows["main_window"].title, "Some Title") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } } /// Testing simple Pop-up with: /// Subtitle: This is a subtitle /// BarTitle: IBM Notifier /// Main Button: Label --> Ok - func test2Popup() throws { - let useCase = "eyJub3RpZmljYXRpb24iOnsidG9waWNJRCI6InVudHJhY2tlZCIsIm1haW5CdXR0b24iOnsibGFiZWwiOiJPSyIsImNhbGxUb0FjdGlvblR5cGUiOiJub25lIiwiY2FsbFRvQWN0aW9uUGF5bG9hZCI6IiJ9LCJoaWRlVGl0bGVCYXJCdXR0b25zIjpmYWxzZSwicmV0YWluVmFsdWVzIjpmYWxzZSwiYWNjZXNzb3J5Vmlld3MiOltdLCJpc01vdmFibGUiOnRydWUsImFsd2F5c09uVG9wIjpmYWxzZSwidHlwZSI6InBvcHVwIiwic3VidGl0bGUiOiJUaGlzIGlzIGEgc3VidGl0bGUiLCJzaWxlbnQiOmZhbHNlLCJzaG93U3VwcHJlc3Npb25CdXR0b24iOmZhbHNlLCJtaW5pYXR1cml6YWJsZSI6ZmFsc2UsImZvcmNlTGlnaHRNb2RlIjpmYWxzZSwibm90aWZpY2F0aW9uSUQiOiJ1bnRyYWNrZWQifSwic2V0dGluZ3MiOnsiaXNWZXJib3NlTW9kZUVuYWJsZWQiOmZhbHNlLCJlbnZpcm9ubWVudCI6InByb2QifX0=" // pragma: allowlist-secret - let app = XCUIApplication() - app.launchArguments = [useCase] - app.launch() - XCTAssert(app.buttons["main_button"].exists) - XCTAssertEqual(app.buttons["main_button"].title, "OK") - XCTAssert(app.staticTexts["popup_subtitle"].exists) - XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") - XCTAssertEqual(app.windows["main_window"].title, "IBM Notifier") - app.terminate() + func testA2Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"OK","callToActionType":"none","callToActionPayload":""},"hideTitleBarButtons":false,"retainValues":false,"accessoryViews":[],"alwaysOnTop":false,"type":"popup","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "OK") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssertEqual(app.windows["main_window"].title, "IBM Notifier") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } } /// Testing simple Pop-up with: @@ -53,18 +66,24 @@ class NAPUITests: XCTestCase { /// Subtitle: This is a subtitle /// Position: top_left /// Main Button: Label --> Ok - func test3Popup() throws { - let useCase = "eyJub3RpZmljYXRpb24iOnsidG9waWNJRCI6InVudHJhY2tlZCIsIm1haW5CdXR0b24iOnsibGFiZWwiOiJPSyIsImNhbGxUb0FjdGlvblR5cGUiOiJub25lIiwiY2FsbFRvQWN0aW9uUGF5bG9hZCI6IiJ9LCJoaWRlVGl0bGVCYXJCdXR0b25zIjpmYWxzZSwicmV0YWluVmFsdWVzIjpmYWxzZSwiYWNjZXNzb3J5Vmlld3MiOltdLCJpc01vdmFibGUiOnRydWUsImFsd2F5c09uVG9wIjpmYWxzZSwidHlwZSI6InBvcHVwIiwidGl0bGUiOiJUaGlzIGlzIGEgdGl0bGUiLCJwb3NpdGlvbiI6InRvcF9sZWZ0Iiwic3VidGl0bGUiOiJUaGlzIGlzIGEgc3VidGl0bGUiLCJzaWxlbnQiOmZhbHNlLCJzaG93U3VwcHJlc3Npb25CdXR0b24iOmZhbHNlLCJtaW5pYXR1cml6YWJsZSI6ZmFsc2UsImJhclRpdGxlIjoiTWFjQElCTSBOb3RpZmljYXRpb25zIiwiZm9yY2VMaWdodE1vZGUiOmZhbHNlLCJub3RpZmljYXRpb25JRCI6InVudHJhY2tlZCJ9LCJzZXR0aW5ncyI6eyJpc1ZlcmJvc2VNb2RlRW5hYmxlZCI6ZmFsc2UsImVudmlyb25tZW50IjoicHJvZCJ9fQ==" // pragma: allowlist-secret - let app = XCUIApplication() - app.launchArguments = [useCase] - app.launch() - XCTAssert(app.buttons["main_button"].exists) - XCTAssertEqual(app.buttons["main_button"].title, "OK") - XCTAssert(app.staticTexts["popup_title"].exists) - XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") - XCTAssert(app.staticTexts["popup_subtitle"].exists) - XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") - app.terminate() + func testA3Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"OK","callToActionType":"none","callToActionPayload":""},"hideTitleBarButtons":false,"retainValues":false,"accessoryViews":[],"alwaysOnTop":false,"type":"popup","title":"This is a title","position":"top_left","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"IBM Notifier","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "OK") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } } /// Testing Pop-up with: @@ -72,18 +91,24 @@ class NAPUITests: XCTestCase { /// Subtitle: This is a subtitle /// Silent: true /// Main Button: Label --> Ok - func test4Popup() throws { - let useCase = "eyJub3RpZmljYXRpb24iOnsidG9waWNJRCI6InVudHJhY2tlZCIsIm1haW5CdXR0b24iOnsibGFiZWwiOiJPSyIsImNhbGxUb0FjdGlvblR5cGUiOiJub25lIiwiY2FsbFRvQWN0aW9uUGF5bG9hZCI6IiJ9LCJoaWRlVGl0bGVCYXJCdXR0b25zIjpmYWxzZSwicmV0YWluVmFsdWVzIjpmYWxzZSwiYWNjZXNzb3J5Vmlld3MiOltdLCJpc01vdmFibGUiOnRydWUsImFsd2F5c09uVG9wIjpmYWxzZSwidHlwZSI6InBvcHVwIiwidGl0bGUiOiJUaGlzIGlzIGEgdGl0bGUiLCJzdWJ0aXRsZSI6IlRoaXMgaXMgYSBzdWJ0aXRsZSIsInNpbGVudCI6dHJ1ZSwic2hvd1N1cHByZXNzaW9uQnV0dG9uIjpmYWxzZSwibWluaWF0dXJpemFibGUiOmZhbHNlLCJiYXJUaXRsZSI6Ik1hY0BJQk0gTm90aWZpY2F0aW9ucyIsImZvcmNlTGlnaHRNb2RlIjpmYWxzZSwibm90aWZpY2F0aW9uSUQiOiJ1bnRyYWNrZWQifSwic2V0dGluZ3MiOnsiaXNWZXJib3NlTW9kZUVuYWJsZWQiOmZhbHNlLCJlbnZpcm9ubWVudCI6InByb2QifX0=" // pragma: allowlist-secret - let app = XCUIApplication() - app.launchArguments = [useCase] - app.launch() - XCTAssert(app.buttons["main_button"].exists) - XCTAssertEqual(app.buttons["main_button"].title, "OK") - XCTAssert(app.staticTexts["popup_title"].exists) - XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") - XCTAssert(app.staticTexts["popup_subtitle"].exists) - XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") - app.terminate() + func testA4Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"OK","callToActionType":"none","callToActionPayload":""},"hideTitleBarButtons":false,"retainValues":false,"accessoryViews":[],"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":true,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"IBM N otifier","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "OK") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } } /// Testing Pop-up with: @@ -91,20 +116,26 @@ class NAPUITests: XCTestCase { /// Subtitle: This is a subtitle /// Main Button: Label --> Primary /// Secondary Button: Label --> Secondary - func test5Popup() throws { - let useCase = "eyJub3RpZmljYXRpb24iOnsidG9waWNJRCI6InVudHJhY2tlZCIsIm1haW5CdXR0b24iOnsibGFiZWwiOiJQcmltYXJ5IiwiY2FsbFRvQWN0aW9uVHlwZSI6Im5vbmUiLCJjYWxsVG9BY3Rpb25QYXlsb2FkIjoiIn0sInNlY29uZGFyeUJ1dHRvbiI6eyJsYWJlbCI6IlNlY29uZGFyeSIsImNhbGxUb0FjdGlvblR5cGUiOiJub25lIiwiY2FsbFRvQWN0aW9uUGF5bG9hZCI6IiJ9LCJoaWRlVGl0bGVCYXJCdXR0b25zIjpmYWxzZSwicmV0YWluVmFsdWVzIjpmYWxzZSwiYWNjZXNzb3J5Vmlld3MiOltdLCJpc01vdmFibGUiOnRydWUsImFsd2F5c09uVG9wIjpmYWxzZSwidHlwZSI6InBvcHVwIiwidGl0bGUiOiJUaGlzIGlzIGEgdGl0bGUiLCJzdWJ0aXRsZSI6IlRoaXMgaXMgYSBzdWJ0aXRsZSIsInNpbGVudCI6ZmFsc2UsInNob3dTdXBwcmVzc2lvbkJ1dHRvbiI6ZmFsc2UsIm1pbmlhdHVyaXphYmxlIjpmYWxzZSwiYmFyVGl0bGUiOiJNYWNASUJNIE5vdGlmaWNhdGlvbnMiLCJmb3JjZUxpZ2h0TW9kZSI6ZmFsc2UsIm5vdGlmaWNhdGlvbklEIjoidW50cmFja2VkIn0sInNldHRpbmdzIjp7ImlzVmVyYm9zZU1vZGVFbmFibGVkIjpmYWxzZSwiZW52aXJvbm1lbnQiOiJwcm9kIn19" // pragma: allowlist-secret - let app = XCUIApplication() - app.launchArguments = [useCase] - app.launch() - XCTAssert(app.buttons["main_button"].exists) - XCTAssertEqual(app.buttons["main_button"].title, "Primary") - XCTAssert(app.buttons["secondary_button"].exists) - XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") - XCTAssert(app.staticTexts["popup_title"].exists) - XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") - XCTAssert(app.staticTexts["popup_subtitle"].exists) - XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") - app.terminate() + func testA5Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"hideTitleBarButtons":false,"retainValues":false,"accessoryViews":[],"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"IBM Notifier","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } } /// Testing Pop-up with: @@ -113,22 +144,28 @@ class NAPUITests: XCTestCase { /// Main Button: Label --> Primary /// Secondary Button: Label --> Secondary /// Tertiary Button: Label --> Tertiary - func test6Popup() throws { - let useCase = "eyJub3RpZmljYXRpb24iOnsidG9waWNJRCI6InVudHJhY2tlZCIsIm1haW5CdXR0b24iOnsibGFiZWwiOiJQcmltYXJ5IiwiY2FsbFRvQWN0aW9uVHlwZSI6Im5vbmUiLCJjYWxsVG9BY3Rpb25QYXlsb2FkIjoiIn0sInNlY29uZGFyeUJ1dHRvbiI6eyJsYWJlbCI6IlNlY29uZGFyeSIsImNhbGxUb0FjdGlvblR5cGUiOiJub25lIiwiY2FsbFRvQWN0aW9uUGF5bG9hZCI6IiJ9LCJ0ZXJ0aWFyeUJ1dHRvbiI6eyJsYWJlbCI6IlRlcnRpYXJ5IiwiY2FsbFRvQWN0aW9uVHlwZSI6ImxpbmsiLCJjYWxsVG9BY3Rpb25QYXlsb2FkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbSJ9LCJoaWRlVGl0bGVCYXJCdXR0b25zIjpmYWxzZSwicmV0YWluVmFsdWVzIjpmYWxzZSwiYWNjZXNzb3J5Vmlld3MiOltdLCJpc01vdmFibGUiOnRydWUsImFsd2F5c09uVG9wIjpmYWxzZSwidHlwZSI6InBvcHVwIiwidGl0bGUiOiJUaGlzIGlzIGEgdGl0bGUiLCJzdWJ0aXRsZSI6IlRoaXMgaXMgYSBzdWJ0aXRsZSIsInNpbGVudCI6ZmFsc2UsInNob3dTdXBwcmVzc2lvbkJ1dHRvbiI6ZmFsc2UsIm1pbmlhdHVyaXphYmxlIjpmYWxzZSwiYmFyVGl0bGUiOiJNYWNASUJNIE5vdGlmaWNhdGlvbnMiLCJmb3JjZUxpZ2h0TW9kZSI6ZmFsc2UsIm5vdGlmaWNhdGlvbklEIjoidW50cmFja2VkIn0sInNldHRpbmdzIjp7ImlzVmVyYm9zZU1vZGVFbmFibGVkIjpmYWxzZSwiZW52aXJvbm1lbnQiOiJwcm9kIn19" // pragma: allowlist-secret - let app = XCUIApplication() - app.launchArguments = [useCase] - app.launch() - XCTAssert(app.buttons["main_button"].exists) - XCTAssertEqual(app.buttons["main_button"].title, "Primary") - XCTAssert(app.buttons["secondary_button"].exists) - XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") - XCTAssert(app.buttons["tertiary_button"].exists) - XCTAssertEqual(app.buttons["tertiary_button"].label, "Tertiary") - XCTAssert(app.staticTexts["popup_title"].exists) - XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") - XCTAssert(app.staticTexts["popup_subtitle"].exists) - XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") - app.terminate() + func testA6Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"tertiaryButton":{"label":"Tertiary","callToActionType":"link","callToActionPayload":"https://www.google.com"},"hideTitleBarButtons":false,"retainValues":false,"accessoryViews":[],"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"IBM Notifier","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.buttons["tertiary_button"].exists) + XCTAssertEqual(app.buttons["tertiary_button"].label, "Tertiary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } } /// Testing Pop-up with: @@ -137,21 +174,27 @@ class NAPUITests: XCTestCase { /// Main Button: Primary /// Secondary Button: Secondary /// BarTitle: Some - func test7Popup() throws { - let useCase = "eyJub3RpZmljYXRpb24iOnsidG9waWNJRCI6InVudHJhY2tlZCIsIm1haW5CdXR0b24iOnsibGFiZWwiOiJQcmltYXJ5IiwiY2FsbFRvQWN0aW9uVHlwZSI6Im5vbmUiLCJjYWxsVG9BY3Rpb25QYXlsb2FkIjoiIn0sInNlY29uZGFyeUJ1dHRvbiI6eyJsYWJlbCI6IlNlY29uZGFyeSIsImNhbGxUb0FjdGlvblR5cGUiOiJub25lIiwiY2FsbFRvQWN0aW9uUGF5bG9hZCI6IiJ9LCJoaWRlVGl0bGVCYXJCdXR0b25zIjpmYWxzZSwicmV0YWluVmFsdWVzIjpmYWxzZSwiYWNjZXNzb3J5Vmlld3MiOltdLCJpc01vdmFibGUiOnRydWUsImFsd2F5c09uVG9wIjpmYWxzZSwidHlwZSI6InBvcHVwIiwidGl0bGUiOiJUaGlzIGlzIGEgdGl0bGUiLCJzdWJ0aXRsZSI6IlRoaXMgaXMgYSBzdWJ0aXRsZSIsInNpbGVudCI6ZmFsc2UsInNob3dTdXBwcmVzc2lvbkJ1dHRvbiI6ZmFsc2UsIm1pbmlhdHVyaXphYmxlIjpmYWxzZSwiYmFyVGl0bGUiOiJTb21lIiwiZm9yY2VMaWdodE1vZGUiOmZhbHNlLCJub3RpZmljYXRpb25JRCI6InVudHJhY2tlZCJ9LCJzZXR0aW5ncyI6eyJpc1ZlcmJvc2VNb2RlRW5hYmxlZCI6ZmFsc2UsImVudmlyb25tZW50IjoicHJvZCJ9fQ==" // pragma: allowlist-secret - let app = XCUIApplication() - app.launchArguments = [useCase] - app.launch() - XCTAssert(app.buttons["main_button"].exists) - XCTAssertEqual(app.buttons["main_button"].title, "Primary") - XCTAssert(app.buttons["secondary_button"].exists) - XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") - XCTAssertEqual(app.windows["main_window"].title, "Some") - XCTAssert(app.staticTexts["popup_title"].exists) - XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") - XCTAssert(app.staticTexts["popup_subtitle"].exists) - XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") - app.terminate() + func testA7Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"hideTitleBarButtons":false,"retainValues":false,"accessoryViews":[],"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssertEqual(app.windows["main_window"].title, "Some") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } } /// Testing Pop-up with: @@ -160,20 +203,941 @@ class NAPUITests: XCTestCase { /// Main Button: Primary /// Secondary Button: Secondary /// Icon: Circle SFSymbol - func test8Popup() throws { - let useCase = "eyJub3RpZmljYXRpb24iOnsidG9waWNJRCI6InVudHJhY2tlZCIsIm1haW5CdXR0b24iOnsibGFiZWwiOiJQcmltYXJ5IiwiY2FsbFRvQWN0aW9uVHlwZSI6Im5vbmUiLCJjYWxsVG9BY3Rpb25QYXlsb2FkIjoiIn0sInNlY29uZGFyeUJ1dHRvbiI6eyJsYWJlbCI6IlNlY29uZGFyeSIsImNhbGxUb0FjdGlvblR5cGUiOiJub25lIiwiY2FsbFRvQWN0aW9uUGF5bG9hZCI6IiJ9LCJpY29uUGF0aCI6ImNpcmNsZSIsImhpZGVUaXRsZUJhckJ1dHRvbnMiOmZhbHNlLCJyZXRhaW5WYWx1ZXMiOmZhbHNlLCJhY2Nlc3NvcnlWaWV3cyI6W10sImlzTW92YWJsZSI6dHJ1ZSwiYWx3YXlzT25Ub3AiOmZhbHNlLCJ0eXBlIjoicG9wdXAiLCJ0aXRsZSI6IlRoaXMgaXMgYSB0aXRsZSIsInN1YnRpdGxlIjoiVGhpcyBpcyBhIHN1YnRpdGxlIiwic2lsZW50IjpmYWxzZSwic2hvd1N1cHByZXNzaW9uQnV0dG9uIjpmYWxzZSwibWluaWF0dXJpemFibGUiOmZhbHNlLCJiYXJUaXRsZSI6IlNvbWUiLCJmb3JjZUxpZ2h0TW9kZSI6ZmFsc2UsIm5vdGlmaWNhdGlvbklEIjoidW50cmFja2VkIn0sInNldHRpbmdzIjp7ImlzVmVyYm9zZU1vZGVFbmFibGVkIjpmYWxzZSwiZW52aXJvbm1lbnQiOiJwcm9kIn19" // pragma: allowlist-secret - let app = XCUIApplication() - app.launchArguments = [useCase] - app.launch() - XCTAssert(app.buttons["main_button"].exists) - XCTAssertEqual(app.buttons["main_button"].title, "Primary") - XCTAssert(app.buttons["secondary_button"].exists) - XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") - XCTAssertEqual(app.images["popup_icon"].label, "circle") - XCTAssert(app.staticTexts["popup_title"].exists) - XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") - XCTAssert(app.staticTexts["popup_subtitle"].exists) - XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") - app.terminate() + func testA8Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"circle","hideTitleBarButtons":false,"retainValues":false,"accessoryViews":[],"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssertEqual(app.images["popup_icon"].label, "circle") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// Icon: Circle SFSymbol + /// AccessoryView: slideshow with 3 images + func testA9Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"circle","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"slideshow","payload":"/images https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg\\nhttps://cdn.pixabay.com/photo/2015/04/19/08/32/rose-729509_960_720.jpg\\nhttps://cdn.pixabay.com/photo/2015/07/05/10/18/tree-832079_960_720.jpg"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.images["accessory_view_slideshow_image"].exists) + XCTAssert(!app.buttons["accessory_view_slideshow_backward_button"].exists) + XCTAssert(app.buttons["accessory_view_slideshow_forward_button"].exists) + app.buttons["accessory_view_slideshow_forward_button"].tap() + XCTAssert(app.buttons["accessory_view_slideshow_forward_button"].exists) + XCTAssert(app.buttons["accessory_view_slideshow_backward_button"].exists) + app.buttons["accessory_view_slideshow_forward_button"].tap() + XCTAssert(app.buttons["accessory_view_slideshow_backward_button"].exists) + XCTAssert(!app.buttons["accessory_view_slideshow_forward_button"].exists) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// Icon: Circle SFSymbol + /// AccessoryView: image + func testB1Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"circle","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"image","payload":"https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.images["image_accessory_view"].exists) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: whitebox + func testB2Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"whitebox","payload":"Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isHittable) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.buttons["secondary_button"].isHittable) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.textViews["markdown_accessory_view"].exists) + XCTAssertEqual(app.textViews["markdown_accessory_view"].value as? String ?? "", "Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: timer + func testB3Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false,"accessoryViews":[{"type":"timer","payload":"Time left: %@"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isHittable) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.buttons["secondary_button"].isHittable) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.staticTexts["timer_accessory_view"].exists) + let firstLabel = app.staticTexts["timer_accessory_view"].value as? String ?? "" + sleep(2) + let secondLabel = app.staticTexts["timer_accessory_view"].value as? String ?? "" + XCTAssertNotEqual(firstLabel, secondLabel) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: input + func testB4Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"input","payload":"/title AV Title /placeholder Some placeholder"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isHittable) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.buttons["secondary_button"].isHittable) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssertEqual(app.staticTexts["input_accessory_view_title"].value as? String ?? "", "AV Title") + XCTAssertEqual(app.textFields["input_accessory_view_textfield"].placeholderValue ?? "", "Some placeholder") + app.textFields["input_accessory_view_textfield"].click() + app.textFields["input_accessory_view_textfield"].typeText("This is the value") + XCTAssertEqual(app.textFields["input_accessory_view_textfield"].value as? String ?? "", "This is the value") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: secureinput + func testB5Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"secureinput","payload":"/title AV Title /placeholder Some secure placeholder"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isHittable) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.buttons["secondary_button"].isHittable) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssertEqual(app.staticTexts["input_accessory_view_title"].value as? String ?? "", "AV Title") + XCTAssertEqual(app.secureTextFields["input_accessory_view_secure_textfield"].placeholderValue ?? "", "Some secure placeholder") + app.secureTextFields["input_accessory_view_secure_textfield"].click() + app.secureTextFields["input_accessory_view_secure_textfield"].typeText("Pass") + XCTAssertEqual(app.secureTextFields["input_accessory_view_secure_textfield"].value as? String ?? "", "") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: progressbar + func testB6Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"progressbar","payload":"/percent 0 /top_message Top /bottom_message Bottom"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssertFalse(app.buttons["main_button"].exists) + XCTAssertFalse(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssertEqual(app.staticTexts["progressbar_accessory_view_top_message"].value as? String ?? "", "Top") + XCTAssert(app.progressIndicators["progressbar_accessory_view_progressview_determined"].exists) + XCTAssertEqual(app.progressIndicators["progressbar_accessory_view_progressview_determined"].value as? CGFloat ?? -1, 0) + XCTAssertEqual(app.staticTexts["progressbar_accessory_view_bottom_message"].value as? String ?? "", "Bottom") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: progressbar + func testB7Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"progressbar","payload":"/percent indeterminate /top_message Top /bottom_message Bottom"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssertFalse(app.buttons["main_button"].exists) + XCTAssertFalse(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssertEqual(app.staticTexts["progressbar_accessory_view_top_message"].value as? String ?? "", "Top") + XCTAssert(app.activityIndicators["progressbar_accessory_view_progressview_indeterminate"].exists) + XCTAssertEqual(app.activityIndicators["progressbar_accessory_view_progressview_indeterminate"].value as? CGFloat ?? -1, 0) + XCTAssertEqual(app.staticTexts["progressbar_accessory_view_bottom_message"].value as? String ?? "", "Bottom") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: progressbar + func testB8Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"progressbar","payload":"/percent 50 /top_message Top /bottom_message Bottom"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssertFalse(app.buttons["main_button"].exists) + XCTAssertFalse(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssertEqual(app.staticTexts["progressbar_accessory_view_top_message"].value as? String ?? "", "Top") + XCTAssert(app.progressIndicators["progressbar_accessory_view_progressview_determined"].exists) + XCTAssertEqual(app.progressIndicators["progressbar_accessory_view_progressview_determined"].value as? CGFloat ?? -1, 0.5) + XCTAssertEqual(app.staticTexts["progressbar_accessory_view_bottom_message"].value as? String ?? "", "Bottom") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: dropdown + func testB9Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"dropdown","payload":"/list First\\nSecond\\nThird /placeholder Pick something /title Some title"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertFalse(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.staticTexts["picker_accessory_view_title"].exists) + XCTAssertEqual(app.staticTexts["picker_accessory_view_title"].value as? String ?? "", "Some title") + XCTAssert(app.popUpButtons["picker_accessory_view_dropdown"].exists) + XCTAssertEqual(app.popUpButtons["picker_accessory_view_dropdown"].value as? String, "Pick something") + app.popUpButtons["picker_accessory_view_dropdown"].click() + XCTAssert(app.popUpButtons["picker_accessory_view_dropdown"].menuItems["First"].exists) + app.popUpButtons["picker_accessory_view_dropdown"].menuItems["First"].click() + sleep(1) + XCTAssertEqual(app.popUpButtons["picker_accessory_view_dropdown"].value as? String, "First") + app.popUpButtons["picker_accessory_view_dropdown"].click() + XCTAssert(app.popUpButtons["picker_accessory_view_dropdown"].menuItems["Second"].exists) + app.popUpButtons["picker_accessory_view_dropdown"].menuItems["Second"].click() + sleep(1) + XCTAssertEqual(app.popUpButtons["picker_accessory_view_dropdown"].value as? String, "Second") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: dropdown + func testC1Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"dropdown","payload":"/list First\\nSecond\\nThird /placeholder Pick something"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertFalse(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.popUpButtons["picker_accessory_view_dropdown"].exists) + XCTAssertEqual(app.popUpButtons["picker_accessory_view_dropdown"].value as? String, "Pick something") + app.popUpButtons["picker_accessory_view_dropdown"].click() + XCTAssert(app.popUpButtons["picker_accessory_view_dropdown"].menuItems["First"].exists) + app.popUpButtons["picker_accessory_view_dropdown"].menuItems["First"].click() + sleep(1) + XCTAssertEqual(app.popUpButtons["picker_accessory_view_dropdown"].value as? String, "First") + XCTAssert(app.buttons["main_button"].isEnabled) + app.popUpButtons["picker_accessory_view_dropdown"].click() + XCTAssert(app.popUpButtons["picker_accessory_view_dropdown"].menuItems["Pick something"].exists) + app.popUpButtons["picker_accessory_view_dropdown"].menuItems["Pick something"].click() + sleep(1) + XCTAssertEqual(app.popUpButtons["picker_accessory_view_dropdown"].value as? String, "Pick something") + XCTAssertFalse(app.buttons["main_button"].isEnabled) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: checklist + func testC2Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"checklist","payload":"/list First\\nSecond\\nThird /title Some title"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.staticTexts["picker_accessory_view_title"].exists) + XCTAssertEqual(app.staticTexts["picker_accessory_view_title"].value as? String ?? "", "Some title") + XCTAssert(app.checkBoxes["picker_accessory_view_checkboxes_First"].exists) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_First"].label, "First") + app.checkBoxes["picker_accessory_view_checkboxes_First"].click() + sleep(1) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_First"].value as? Bool, true) + XCTAssert(app.checkBoxes["picker_accessory_view_checkboxes_Second"].exists) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_Second"].label, "Second") + app.checkBoxes["picker_accessory_view_checkboxes_Second"].click() + sleep(1) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_Second"].value as? Bool, true) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: checklist + func testC3Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"checklist","payload":"/list First\\nSecond\\nThird /required"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertFalse(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.checkBoxes["picker_accessory_view_checkboxes_First"].exists) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_First"].label, "First") + app.checkBoxes["picker_accessory_view_checkboxes_First"].click() + sleep(1) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_First"].value as? Bool, true) + XCTAssert(app.buttons["main_button"].isEnabled) + app.checkBoxes["picker_accessory_view_checkboxes_First"].click() + sleep(1) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_First"].value as? Bool, false) + XCTAssertFalse(app.buttons["main_button"].isEnabled) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: checklist + func testC4Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"checklist","payload":"/list First\\nSecond\\nThird /complete"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertFalse(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.checkBoxes["picker_accessory_view_checkboxes_First"].exists) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_First"].label, "First") + app.checkBoxes["picker_accessory_view_checkboxes_First"].click() + sleep(1) + XCTAssertFalse(app.buttons["main_button"].isEnabled) + app.checkBoxes["picker_accessory_view_checkboxes_Second"].click() + app.checkBoxes["picker_accessory_view_checkboxes_Third"].click() + sleep(1) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_First"].value as? Bool, true) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_Second"].value as? Bool, true) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_Third"].value as? Bool, true) + XCTAssert(app.buttons["main_button"].isEnabled) + app.checkBoxes["picker_accessory_view_checkboxes_First"].click() + sleep(1) + XCTAssertFalse(app.buttons["main_button"].isEnabled) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: checklist + func testC5Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"checklist","payload":"/list First\\nSecond\\nThird /preselection 1 /required"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.checkBoxes["picker_accessory_view_checkboxes_Second"].exists) + XCTAssertEqual(app.checkBoxes["picker_accessory_view_checkboxes_Second"].label, "Second") + app.checkBoxes["picker_accessory_view_checkboxes_Second"].click() + sleep(1) + XCTAssertFalse(app.buttons["main_button"].isEnabled) + app.checkBoxes["picker_accessory_view_checkboxes_Second"].click() + sleep(1) + XCTAssert(app.buttons["main_button"].isEnabled) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: checklist - radio + func testC6Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"checklist","payload":"/list First\\nSecond\\nThird /radio /required /title Some title"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertFalse(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.staticTexts["picker_accessory_view_title"].exists) + XCTAssertEqual(app.staticTexts["picker_accessory_view_title"].value as? String ?? "", "Some title") + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].exists) + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["First"].exists) + app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["First"].click() + sleep(1) + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["First"].isSelected) + XCTAssert(app.buttons["main_button"].isEnabled) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: checklist - radio + func testC7Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"checklist","payload":"/list First\\nSecond\\nThird /radio"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].exists) + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["First"].exists) + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["Second"].exists) + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["Third"].exists) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: checklist - radio + func testC8Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"checklist","payload":"/list First\\nSecond\\nThird /radio /preselection 1"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].exists) + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["First"].exists) + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["Second"].exists) + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["Second"].isSelected) + XCTAssert(app.radioGroups["picker_accessory_view_radio_buttons"].radioButtons["Third"].exists) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: datepicker + func testC9Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"datepicker","payload":"/title Some title"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.staticTexts["datepicker_accessory_view_title"].exists) + XCTAssertEqual(app.staticTexts["datepicker_accessory_view_title"].value as? String ?? "", "Some title") + XCTAssert(app.datePickers["datepicker_accessory_view_picker"].exists) + XCTAssert(app.datePickers["datepicker_accessory_view_picker"].isEnabled) + XCTAssertNotNil(app.datePickers["datepicker_accessory_view_picker"].value) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: datepicker + func testD1Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"datepicker","payload":"/title Some title /style graphical"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.staticTexts["datepicker_accessory_view_title"].exists) + XCTAssertEqual(app.staticTexts["datepicker_accessory_view_title"].value as? String ?? "", "Some title") + XCTAssert(app.datePickers["datepicker_accessory_view_picker"].exists) + XCTAssert(app.datePickers["datepicker_accessory_view_picker"].isHittable) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// AccessoryView: datepicker + func testD2Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"datepicker","payload":"/title Some title /style graphical /components date"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.staticTexts["datepicker_accessory_view_title"].exists) + XCTAssertEqual(app.staticTexts["datepicker_accessory_view_title"].value as? String ?? "", "Some title") + XCTAssert(app.datePickers["datepicker_accessory_view_picker"].exists) + XCTAssert(app.datePickers["datepicker_accessory_view_picker"].isHittable) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// Custom Width: 1000 + /// AccessoryView: whitebox + func testD3Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","customWidth":"1000","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"whitebox","payload":"Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isHittable) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.buttons["secondary_button"].isHittable) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.textViews["markdown_accessory_view"].exists) + XCTAssertEqual(app.textViews["markdown_accessory_view"].value as? String ?? "", "Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view Some text in the whitebox accessory view") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// Unmovable: true + func testD4Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":false,"disableQuit":false,"buttonless":false, "accessoryViews":[]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.windows["main_window"].exists) + XCTAssert(app.windows["main_window"].isHittable) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + let initialPositionY = app.windows["main_window"].frame.minY + let initialPositionX = app.windows["main_window"].frame.minX + let coordinate = app.windows["main_window"].coordinate(withNormalizedOffset: CGVector(dx: 0.02, dy: 0.04)) + coordinate.click(forDuration: 1, thenDragTo: app.buttons["main_button"].coordinate(withNormalizedOffset: .zero)) + let finalPositionY = app.windows["main_window"].frame.minY + let finalPositionX = app.windows["main_window"].frame.minX + XCTAssert(initialPositionX == finalPositionX) + XCTAssert(initialPositionY == finalPositionY) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// Unmovable: false + func testD5Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"timeout":"30","barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.windows["main_window"].exists) + XCTAssert(app.windows["main_window"].isHittable) + XCTAssert(app.buttons["main_button"].exists) + XCTAssert(app.buttons["main_button"].isEnabled) + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + let initialPositionY = app.windows["main_window"].frame.minY + let initialPositionX = app.windows["main_window"].frame.minX + let coordinate = app.windows["main_window"].coordinate(withNormalizedOffset: CGVector(dx: 0.02, dy: 0.04)) + coordinate.click(forDuration: 1, thenDragTo: app.buttons["main_button"].coordinate(withNormalizedOffset: .zero)) + let finalPositionY = app.windows["main_window"].frame.minY + let finalPositionX = app.windows["main_window"].frame.minX + XCTAssertFalse(initialPositionX == finalPositionX) + XCTAssertFalse(initialPositionY == finalPositionY) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// BarTitle: Some Title + /// Buttonless: true + func testD6Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"OK","callToActionType":"none","callToActionPayload":""},"hideTitleBarButtons":false,"retainValues":false,"accessoryViews":[],"alwaysOnTop":false,"type":"popup","title":"This is a title","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some Title","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":true},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + + XCTAssertFalse(app.buttons["main_button"].exists) + XCTAssertEqual(app.images["popup_icon"].label, "default_icon") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssertEqual(app.windows["main_window"].title, "Some Title") + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// Icon: Circle SFSymbol + /// AccessoryView: image with a GIF + func testD7Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"circle","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"image","payload":"https://compote.slate.com/images/697b023b-64a5-49a0-8059-27b963453fb1.gif?crop=780%2C520%2Cx0%2Cy0&width=2200"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.images["image_accessory_view"].exists) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } + } + + /// Testing Pop-up with: + /// Title: This is a title + /// Subtitle: This is a subtitle + /// Main Button: Primary + /// Secondary Button: Secondary + /// Icon: Circle SFSymbol + /// AccessoryView: image with a GIF + /// Secondary AccessoryView: image + func testD8Popup() throws { + let useCase = """ + {"notification":{"topicID":"untracked","mainButton":{"label":"Primary","callToActionType":"none","callToActionPayload":""},"secondaryButton":{"label":"Secondary","callToActionType":"none","callToActionPayload":""},"iconPath":"circle","hideTitleBarButtons":false,"retainValues":false,"alwaysOnTop":false,"type":"popup","title":"This is a title","subtitle":"This is a subtitle","silent":false,"showSuppressionButton":false,"miniaturizable":false,"barTitle":"Some","forceLightMode":false,"notificationID":"untracked","isMovable":true,"disableQuit":false,"buttonless":false, "accessoryViews":[{"type":"image","payload":"https://compote.slate.com/images/697b023b-64a5-49a0-8059-27b963453fb1.gif?crop=780%2C520%2Cx0%2Cy0&width=2200"},{"type":"image","payload":"https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_1280.jpg"}]},"settings":{"isVerboseModeEnabled":false,"environment":"prod"}} + """ // pragma: allowlist-secret + if let useCaseData = useCase.data(using: .utf8) { + let app = XCUIApplication() + app.launchArguments = [useCaseData.base64EncodedString()] + app.launch() + XCTAssert(app.buttons["main_button"].exists) + XCTAssertEqual(app.buttons["main_button"].title, "Primary") + XCTAssert(app.buttons["secondary_button"].exists) + XCTAssertEqual(app.buttons["secondary_button"].label, "Secondary") + XCTAssert(app.staticTexts["popup_title"].exists) + XCTAssertEqual(app.staticTexts["popup_title"].value as? String ?? "", "This is a title") + XCTAssert(app.staticTexts["popup_subtitle"].exists) + XCTAssertEqual(app.staticTexts["popup_subtitle"].value as? String ?? "", "This is a subtitle") + XCTAssert(app.images["image_accessory_view"].exists) + app.terminate() + } else { + XCTAssert(false, "Failed to encode the usecase.") + } } } +// swiftlint:enable type_body_length file_length diff --git a/Notification Agent Popups/AppDelegate.swift b/Notification Agent Popups/AppDelegate.swift index fb2f4bd..f12eb6c 100644 --- a/Notification Agent Popups/AppDelegate.swift +++ b/Notification Agent Popups/AppDelegate.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 18/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // @@ -35,6 +35,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { NSEvent.addLocalMonitorForEvents(matching: .keyDown) { event in switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) { case [.command] where event.characters == "q": + guard !self.context.disableQuit else { return .none } Utils.applicationExit(withReason: .userDismissedPopup) default: return event diff --git a/Notification Agent Popups/Controllers/PopupInteractiveEFCLController.swift b/Notification Agent Popups/Controllers/PopupInteractiveEFCLController.swift index fc9db53..21a8e83 100644 --- a/Notification Agent Popups/Controllers/PopupInteractiveEFCLController.swift +++ b/Notification Agent Popups/Controllers/PopupInteractiveEFCLController.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 24/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Popups/Controllers/SystemAlertController.swift b/Notification Agent Popups/Controllers/SystemAlertController.swift index 58a0ca4..8446372 100644 --- a/Notification Agent Popups/Controllers/SystemAlertController.swift +++ b/Notification Agent Popups/Controllers/SystemAlertController.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 17/08/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Notification Agent Popups/Extensions/NotificationDispatch-Extension.swift b/Notification Agent Popups/Extensions/NotificationDispatch-Extension.swift index 3d2d053..a1cee12 100644 --- a/Notification Agent Popups/Extensions/NotificationDispatch-Extension.swift +++ b/Notification Agent Popups/Extensions/NotificationDispatch-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 5/27/21. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // @@ -25,7 +25,8 @@ extension NotificationDispatch { } case .popup: DispatchQueue.main.async { - let mainWindow = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 520, height: 130), styleMask: .titled, backing: .buffered, defer: false) + let windowWidth = CGFloat(truncating: NumberFormatter().number(from: object.customWidth ?? "520") ?? .init(integerLiteral: 520)) + let mainWindow = NSWindow(contentRect: NSRect(x: 0, y: 0, width: windowWidth, height: 130), styleMask: .titled, backing: .buffered, defer: false) let viewModel = PopUpViewModel(object, window: mainWindow) let contentView = PopUpView(viewModel: viewModel) let hostingView = NSHostingView(rootView: contentView) diff --git a/Notification Agent Popups/Views/BodyLabels.swift b/Notification Agent Popups/Views/BodyLabels.swift index e73af4e..7dce2d8 100644 --- a/Notification Agent Popups/Views/BodyLabels.swift +++ b/Notification Agent Popups/Views/BodyLabels.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 22/11/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -13,6 +13,10 @@ import SwiftyMarkdown /// BodyLabels is a struct that defines a view with the title and the subtitle for the PupUpView. struct BodyLabels: View { + // MARK: - Environment Variables + + @EnvironmentObject var viewSpec: ViewSpec + // MARK: - Variables var title: String? @@ -30,7 +34,7 @@ struct BodyLabels: View { .accessibilityIdentifier("popup_title") } if let subtitle = subtitle { - MarkdownView(text: subtitle.localized, maxViewHeight: 450) + MarkdownView(text: subtitle.localized, maxViewHeight: 450, containerWidth: viewSpec.accessoryViewWidth) .accessibilityElement() .accessibilityValue(SwiftyMarkdown(string: subtitle).attributedString().string) .accessibilityAddTraits(.isStaticText) diff --git a/Notification Agent Popups/Views/PopUpView.swift b/Notification Agent Popups/Views/PopUpView.swift index a059d80..a46a46f 100644 --- a/Notification Agent Popups/Views/PopUpView.swift +++ b/Notification Agent Popups/Views/PopUpView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 04/11/22. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -22,7 +22,7 @@ struct PopUpView: View { var body: some View { HStack(alignment: .top, spacing: 8) { VStack(alignment: .leading) { - Icon(icon: viewModel.customPopupIcon, iconSize: viewModel.iconSize) + Icon(icon: viewModel.customPopupIcon, iconSize: viewModel.viewSpec.iconSize) .accessibilityIdentifier("popup_icon") Spacer(minLength: 8) HStack(spacing: 4) { @@ -52,7 +52,8 @@ struct PopUpView: View { BodyLabels(title: viewModel.notificationObject.title, titleFont: viewModel.titleFont, subtitle: viewModel.notificationObject.subtitle) - Spacer(minLength: 8) + .environmentObject(viewModel.viewSpec) + .padding(.bottom, 8) if let primaryAV = viewModel.primaryAccessoryView { switch primaryAV.accessoryView.type { case .timer: @@ -61,7 +62,7 @@ struct PopUpView: View { .accessibilityIdentifier("timer_accessory_view") default: AccessoryViewWrapper(source: primaryAV) - .accessibilityIdentifier("primary_accessory_view") + .environmentObject(viewModel.viewSpec) } } if let secondaryAV = viewModel.secondaryAccessoryView { @@ -72,7 +73,7 @@ struct PopUpView: View { .accessibilityIdentifier("timer_accessory_view") default: AccessoryViewWrapper(source: secondaryAV) - .accessibilityIdentifier("secondary_accessory_view") + .environmentObject(viewModel.viewSpec) } } Spacer(minLength: 12) @@ -97,7 +98,7 @@ struct PopUpView: View { } } .padding(EdgeInsets(top: 16, leading: 16, bottom: 16, trailing: 16)) - .frame(width: 520) + .frame(width: viewModel.viewSpec.mainViewWidth) } } diff --git a/Notification Agent Popups/Views/PopUpViewModel.swift b/Notification Agent Popups/Views/PopUpViewModel.swift index 3f48086..639c488 100644 --- a/Notification Agent Popups/Views/PopUpViewModel.swift +++ b/Notification Agent Popups/Views/PopUpViewModel.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 04/11/22. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // // swiftlint:disable type_body_length file_length @@ -62,16 +62,6 @@ class PopUpViewModel: ObservableObject { } return nil } - var iconSize: CGSize { - if let widthString = notificationObject.iconWidth, - let width = NumberFormatter().number(from: widthString), - let heightString = notificationObject.iconHeight, - let height = NumberFormatter().number(from: heightString) { - return CGSize(width: CGFloat(truncating: width), height: CGFloat(truncating: height)) - } else { - return CGSize(width: 60, height: 60) - } - } // MARK: - Variables @@ -87,6 +77,7 @@ class PopUpViewModel: ObservableObject { var reminderTimer: Timer? var timeoutTimer: Timer? var countDown: Int = 0 + var viewSpec: ViewSpec // MARK: - Published Variables @@ -114,11 +105,22 @@ class PopUpViewModel: ObservableObject { self.notificationObject = notificationObject self.window = window mainButton = notificationObject.mainButton - mainButtonState = .enabled - secondaryButtonState = notificationObject.secondaryButton != nil ? .enabled : .hidden + mainButtonState = notificationObject.buttonless ? .hidden : .enabled + secondaryButtonState = notificationObject.secondaryButton != nil ? (notificationObject.buttonless ? .hidden : .enabled) : .hidden tertiaryButtonState = notificationObject.tertiaryButton != nil ? .enabled : .hidden helpButtonState = notificationObject.helpButton != nil ? .enabled : .hidden warningButtonState = notificationObject.warningButton?.isVisible ?? false ? .enabled : .hidden + let viewWidth = CGFloat(truncating: NumberFormatter().number(from: notificationObject.customWidth ?? "520") ?? .init(integerLiteral: 520)) + var iconSize: CGSize = .zero + if let widthString = notificationObject.iconWidth, + let width = NumberFormatter().number(from: widthString), + let heightString = notificationObject.iconHeight, + let height = NumberFormatter().number(from: heightString) { + iconSize = CGSize(width: CGFloat(truncating: width), height: CGFloat(truncating: height)) + } else { + iconSize = CGSize(width: 60, height: 60) + } + viewSpec = ViewSpec(mainViewWidth: viewWidth, iconSize: iconSize) NotificationCenter.default.addObserver(self, selector: #selector(repositionWindow), name: NSApplication.didChangeScreenParametersNotification, object: nil) @@ -177,6 +179,7 @@ class PopUpViewModel: ObservableObject { mainButtonState = { guard primaryAccessoryView != nil else { return .enabled } guard secondaryAccessoryView != nil else { return primaryAVMainButtonState } + guard !notificationObject.buttonless else { return .hidden } switch primaryAVMainButtonState { case .enabled: return secondaryAVMainButtonState @@ -192,6 +195,7 @@ class PopUpViewModel: ObservableObject { secondaryButtonState = { guard primaryAccessoryView != nil else { return .enabled } guard secondaryAccessoryView != nil else { return primaryAVSecButtonState } + guard !notificationObject.buttonless else { return .hidden } switch primaryAVSecButtonState { case .enabled: return secondaryAVSecButtonState diff --git a/Notification Agent.xcodeproj/project.pbxproj b/Notification Agent.xcodeproj/project.pbxproj index a9462e5..6397916 100644 --- a/Notification Agent.xcodeproj/project.pbxproj +++ b/Notification Agent.xcodeproj/project.pbxproj @@ -7,6 +7,30 @@ objects = { /* Begin PBXBuildFile section */ + 1B0FFD3E2B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD3F2B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD402B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD412B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD422B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD432B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD442B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD452B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD462B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD472B20788E00E69392 /* Data-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */; }; + 1B0FFD762B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B0FFD772B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B0FFD782B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B0FFD792B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B0FFD7A2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B0FFD7B2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B0FFD7C2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B0FFD7D2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B0FFD7E2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B0FFD7F2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */; }; + 1B4B58CC2AF941BF0042A192 /* ViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B4B58CB2AF941BF0042A192 /* ViewSpec.swift */; }; + 1B4B58CD2AF941BF0042A192 /* ViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B4B58CB2AF941BF0042A192 /* ViewSpec.swift */; }; + 1B4B58CE2AF941BF0042A192 /* ViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B4B58CB2AF941BF0042A192 /* ViewSpec.swift */; }; + 1B4B58CF2AF941BF0042A192 /* ViewSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B4B58CB2AF941BF0042A192 /* ViewSpec.swift */; }; 1B5AFAEF2A52BCE700F777E1 /* ControlActionClosureProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B5AFAEE2A52BCE700F777E1 /* ControlActionClosureProtocol.swift */; }; 1B5AFAF02A52BCE700F777E1 /* ControlActionClosureProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B5AFAEE2A52BCE700F777E1 /* ControlActionClosureProtocol.swift */; }; 1B5AFAF12A52BCE700F777E1 /* ControlActionClosureProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B5AFAEE2A52BCE700F777E1 /* ControlActionClosureProtocol.swift */; }; @@ -173,6 +197,10 @@ 1B5AFBD12A52FC9800F777E1 /* PageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B5AFBCF2A52FC9800F777E1 /* PageViewModel.swift */; }; 1BFAB6012AA7248C009307C6 /* RichText in Frameworks */ = {isa = PBXBuildFile; productRef = 1BFAB6002AA7248C009307C6 /* RichText */; }; 1BFAB6032AA72496009307C6 /* RichText in Frameworks */ = {isa = PBXBuildFile; productRef = 1BFAB6022AA72496009307C6 /* RichText */; }; + 1BFAB6052AA85ABD009307C6 /* SlideShowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BFAB6042AA85ABD009307C6 /* SlideShowView.swift */; }; + 1BFAB6062AA85ABD009307C6 /* SlideShowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BFAB6042AA85ABD009307C6 /* SlideShowView.swift */; }; + 1BFAB6072AA85ABD009307C6 /* SlideShowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BFAB6042AA85ABD009307C6 /* SlideShowView.swift */; }; + 1BFAB6082AA85ABD009307C6 /* SlideShowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BFAB6042AA85ABD009307C6 /* SlideShowView.swift */; }; B9013A8D24F80C0F009A4554 /* HelpBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9013A8C24F80C0F009A4554 /* HelpBuilder.swift */; }; B9064C0D276BAF240085FA31 /* PopupReminder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9064C0C276BAF240085FA31 /* PopupReminder.swift */; }; B9064C0E276BAF240085FA31 /* PopupReminder.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9064C0C276BAF240085FA31 /* PopupReminder.swift */; }; @@ -740,6 +768,9 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data-Extension.swift"; sourceTree = ""; }; + 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageViewRepresentable.swift; sourceTree = ""; }; + 1B4B58CB2AF941BF0042A192 /* ViewSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewSpec.swift; sourceTree = ""; }; 1B5AFAEE2A52BCE700F777E1 /* ControlActionClosureProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlActionClosureProtocol.swift; sourceTree = ""; }; 1B5AFAF52A52BD2F00F777E1 /* BackPanelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackPanelController.swift; sourceTree = ""; }; 1B5AFAFE2A52EC4400F777E1 /* SwiftUIButtonState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIButtonState.swift; sourceTree = ""; }; @@ -778,6 +809,7 @@ 1B5AFBCC2A52FC8400F777E1 /* PageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageView.swift; sourceTree = ""; }; 1B5AFBCF2A52FC9800F777E1 /* PageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageViewModel.swift; sourceTree = ""; }; 1BFAB5FF2A9F281C009307C6 /* ATTRIBUTIONS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = ATTRIBUTIONS.md; sourceTree = ""; }; + 1BFAB6042AA85ABD009307C6 /* SlideShowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlideShowView.swift; sourceTree = ""; }; B9013A8A24F7E5E5009A4554 /* NALogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NALogger.swift; sourceTree = ""; }; B9013A8C24F80C0F009A4554 /* HelpBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpBuilder.swift; sourceTree = ""; }; B9064C0C276BAF240085FA31 /* PopupReminder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PopupReminder.swift; sourceTree = ""; }; @@ -996,12 +1028,13 @@ children = ( 1B5AFB282A52EE3C00F777E1 /* ProgressBar */, 1B5AFB212A52EE3C00F777E1 /* ViewRepresentable */, - 1B5AFB252A52EE3C00F777E1 /* PickerView.swift */, + 1B5AFB2B2A52EE3C00F777E1 /* AccessoryViewWrapper.swift */, 1B5AFB262A52EE3C00F777E1 /* AccessoryViewSource.swift */, 1B5AFB272A52EE3C00F777E1 /* MediaView.swift */, - 1B5AFB2B2A52EE3C00F777E1 /* AccessoryViewWrapper.swift */, - 1B5AFB2C2A52EE3C00F777E1 /* DatePickerView.swift */, 1B5AFB2D2A52EE3C00F777E1 /* InputView.swift */, + 1B5AFB252A52EE3C00F777E1 /* PickerView.swift */, + 1BFAB6042AA85ABD009307C6 /* SlideShowView.swift */, + 1B5AFB2C2A52EE3C00F777E1 /* DatePickerView.swift */, ); path = SwiftUI; sourceTree = ""; @@ -1011,6 +1044,7 @@ children = ( 1B5AFB222A52EE3C00F777E1 /* MarkdownView.swift */, 1B5AFB232A52EE3C00F777E1 /* HTMLView.swift */, + 1B0FFD752B2078AD00E69392 /* ImageViewRepresentable.swift */, 1B5AFB242A52EE3C00F777E1 /* PlayerView.swift */, ); path = ViewRepresentable; @@ -1265,6 +1299,7 @@ isa = PBXGroup; children = ( B9A03A9A24B76511005BB90E /* NotificationObject.swift */, + 1B4B58CB2AF941BF0042A192 /* ViewSpec.swift */, B92E6707253893D900F39949 /* ProgressState.swift */, B9A03A9E24B779B8005BB90E /* NotificationAccessoryElement.swift */, B9A8852125B9B10600081C8D /* OnboardingData.swift */, @@ -1326,6 +1361,7 @@ B9504D23275EA00B00DD78C5 /* UNNotificationAttachment-Extension.swift */, B9A8855525BB404000081C8D /* Decodable-Extensions.swift */, B9524D2D24E15B1F007662C8 /* String-Extension.swift */, + 1B0FFD3D2B20788E00E69392 /* Data-Extension.swift */, B985DAC9263854EA004F3470 /* NSScreen-Extension.swift */, B9524D3724E17E7F007662C8 /* Int-Extension.swift */, B94389F1262889FB008E314A /* NSColor-Extension.swift */, @@ -1721,7 +1757,7 @@ attributes = { BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 1340; - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1500; ORGANIZATIONNAME = IBM; TargetAttributes = { B920D4B8265F8FC600437BE6 = { @@ -1963,6 +1999,7 @@ B920D4EA265F90EB00437BE6 /* NSColor-Extension.swift in Sources */, 1B5AFBAA2A52EFE600F777E1 /* Binding-Extension.swift in Sources */, B920D4E5265F90E200437BE6 /* NAError.swift in Sources */, + 1B0FFD772B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, FD1730162875B9A000781A69 /* InteractiveObjectProtocol.swift in Sources */, B920D4CE265F90C700437BE6 /* Environment.swift in Sources */, 1B5AFAF62A52BD2F00F777E1 /* BackPanelController.swift in Sources */, @@ -1972,6 +2009,7 @@ B920D4D7265F90D200437BE6 /* ReplyHandler.swift in Sources */, B920D4ED265F90EB00437BE6 /* String-Extension.swift in Sources */, B9360EBD268A06FE00217247 /* EFCLController.swift in Sources */, + 1B0FFD3F2B20788E00E69392 /* Data-Extension.swift in Sources */, B920D502265F927B00437BE6 /* NotificationDispatch-Extension.swift in Sources */, B94BDAD52684C1AB00663D21 /* Token.swift in Sources */, B920D4E1265F90E200437BE6 /* LoadableNib.swift in Sources */, @@ -2014,6 +2052,7 @@ 1B5AFBBC2A52FBA700F777E1 /* BodyLabels.swift in Sources */, 1B5AFB6B2A52EEB700F777E1 /* BackPanelWindow.swift in Sources */, B961A51E267A4D7F00657930 /* LoadableNib.swift in Sources */, + 1BFAB6052AA85ABD009307C6 /* SlideShowView.swift in Sources */, 1B5AFBC02A52FBB900F777E1 /* PopUpView.swift in Sources */, B961A516267A4D6600657930 /* OnboardingData.swift in Sources */, B961A512267A4D5900657930 /* NALogger.swift in Sources */, @@ -2054,8 +2093,10 @@ B961A531267A4DC700657930 /* FlippedStackView.swift in Sources */, B9360EA8268A00E100217247 /* EFCLController.swift in Sources */, B961A4F6267A483900657930 /* NotificationDispatch-Extension.swift in Sources */, + 1B4B58CC2AF941BF0042A192 /* ViewSpec.swift in Sources */, B961A51D267A4D7D00657930 /* NAMedia.swift in Sources */, B961A517267A4D6800657930 /* NotificationButton.swift in Sources */, + 1B0FFD412B20788E00E69392 /* Data-Extension.swift in Sources */, B9064C10276BAF240085FA31 /* PopupReminder.swift in Sources */, B92C37772701D933006114A3 /* InteractiveEFCLContoller.swift in Sources */, 1B5AFB4E2A52EE3C00F777E1 /* AccessoryViewSource.swift in Sources */, @@ -2069,6 +2110,7 @@ 1B5AFB522A52EE3C00F777E1 /* MediaView.swift in Sources */, B961A50F267A4D3C00657930 /* Environment.swift in Sources */, FD0D02D528D9F8AE00A167B7 /* SystemAlertController.swift in Sources */, + 1B0FFD792B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, FD1730182875B9A000781A69 /* InteractiveObjectProtocol.swift in Sources */, 1B5AFB932A52EF9500F777E1 /* View-Extension.swift in Sources */, 1B5AFB012A52EC4400F777E1 /* SwiftUIButtonState.swift in Sources */, @@ -2096,6 +2138,7 @@ B961A5A9267B44B400657930 /* NSScreen-Extension.swift in Sources */, 1B5AFB6C2A52EEB700F777E1 /* BackPanelWindow.swift in Sources */, B961A5B9267B458C00657930 /* Context.swift in Sources */, + 1BFAB6062AA85ABD009307C6 /* SlideShowView.swift in Sources */, FD8A35422863582A00DA72CC /* EFCLController-Extension.swift in Sources */, B961A62A267C80C100657930 /* TaskManager.swift in Sources */, 1B5AFB3B2A52EE3C00F777E1 /* AccessoryView.swift in Sources */, @@ -2136,8 +2179,10 @@ B961A5D9267B89CE00657930 /* LoadableNib.swift in Sources */, B961A5DC267B89CE00657930 /* NAMedia.swift in Sources */, FD1730192875B9A000781A69 /* InteractiveObjectProtocol.swift in Sources */, + 1B4B58CD2AF941BF0042A192 /* ViewSpec.swift in Sources */, B961A5A7267B44B400657930 /* Decodable-Extensions.swift in Sources */, 1B5AFAF92A52BD2F00F777E1 /* BackPanelController.swift in Sources */, + 1B0FFD422B20788E00E69392 /* Data-Extension.swift in Sources */, B961A5A6267B44B400657930 /* String-Extension.swift in Sources */, 1B5AFB022A52EC4400F777E1 /* SwiftUIButtonState.swift in Sources */, B961A5F1267B8A2600657930 /* HorizontalLine.swift in Sources */, @@ -2151,6 +2196,7 @@ 1B5AFB532A52EE3C00F777E1 /* MediaView.swift in Sources */, B961A5D7267B89CE00657930 /* NotificationObject.swift in Sources */, B961A582267A5CDA00657930 /* Utils.swift in Sources */, + 1B0FFD7A2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, B961A5DD267B89CE00657930 /* NotificationButton.swift in Sources */, 1B5AFB942A52EF9500F777E1 /* View-Extension.swift in Sources */, B961A5D6267B89CE00657930 /* NAError.swift in Sources */, @@ -2176,6 +2222,7 @@ B961A4B52673676000657930 /* ReplyHandler.swift in Sources */, 1B5AFBAB2A52EFE600F777E1 /* Binding-Extension.swift in Sources */, FD8A35402863582900DA72CC /* EFCLController-Extension.swift in Sources */, + 1B0FFD782B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, B961A4B02673676000657930 /* LoadableNib.swift in Sources */, FD1730172875B9A000781A69 /* InteractiveObjectProtocol.swift in Sources */, B961A49F2673673C00657930 /* UserNotificationController.swift in Sources */, @@ -2185,6 +2232,7 @@ B961A4A02673673F00657930 /* Context.swift in Sources */, B9360EBE268A06FF00217247 /* EFCLController.swift in Sources */, B961A4A92673676000657930 /* InfoSection.swift in Sources */, + 1B0FFD402B20788E00E69392 /* Data-Extension.swift in Sources */, B94BDAD62684C1AB00663D21 /* Token.swift in Sources */, B961A4BB2673677C00657930 /* NSColor-Extension.swift in Sources */, B961A4B72673677C00657930 /* String-Extension.swift in Sources */, @@ -2247,6 +2295,7 @@ B961A625267C7DFE00657930 /* InteractiveEFCLContoller.swift in Sources */, B9C711822681DBC200A3E898 /* TaskObject.swift in Sources */, 1B5AFBA92A52EFE600F777E1 /* Binding-Extension.swift in Sources */, + 1B0FFD3E2B20788E00E69392 /* Data-Extension.swift in Sources */, B9360EC6268A0AE800217247 /* NotificationDispatch-Extension.swift in Sources */, B9C7A9CA24D16F790038D4A7 /* NotificationDispatch.swift in Sources */, FD1730152875B9A000781A69 /* InteractiveObjectProtocol.swift in Sources */, @@ -2254,6 +2303,7 @@ 1B5AFB9E2A52EFC200F777E1 /* Collection-Extension.swift in Sources */, B961A4D42677AFB000657930 /* EFCLController.swift in Sources */, B961A4F42679F50E00657930 /* TaskManager.swift in Sources */, + 1B0FFD762B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, B9524D2E24E15B1F007662C8 /* String-Extension.swift in Sources */, B9A03A9F24B779B8005BB90E /* NotificationAccessoryElement.swift in Sources */, ); @@ -2265,6 +2315,7 @@ files = ( 1B5AFBB82A52F03F00F777E1 /* ActionTrampoline.swift in Sources */, FDFCA5712857CF71009C1880 /* NALogger.swift in Sources */, + 1B0FFD432B20788E00E69392 /* Data-Extension.swift in Sources */, FD17300F2875B82000781A69 /* DynamicNotificationButton.swift in Sources */, FDFCA5542857CED7009C1880 /* NAError.swift in Sources */, FDFCA5602857CEF3009C1880 /* String-Extension.swift in Sources */, @@ -2279,6 +2330,7 @@ FDFCA5642857CEF3009C1880 /* Notification-Extension.swift in Sources */, FDFCA55D2857CED7009C1880 /* OnboardingData.swift in Sources */, FDFCA56A2857CF71009C1880 /* EFCLController-Extension.swift in Sources */, + 1B0FFD7B2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, FDFCA56C2857CF71009C1880 /* DeepLinkEngine.swift in Sources */, FDFCA54E2857CED7009C1880 /* ConfigurableParameters.swift in Sources */, FDFCA5512857CED7009C1880 /* Claims.swift in Sources */, @@ -2327,6 +2379,7 @@ FDC346CB2858C458001F2212 /* SharedSettings.swift in Sources */, FDC346B12858C43F001F2212 /* OnboardingData.swift in Sources */, FDC346D32858C458001F2212 /* NAError.swift in Sources */, + 1B0FFD442B20788E00E69392 /* Data-Extension.swift in Sources */, FDC346932858C412001F2212 /* EFCLController.swift in Sources */, FDC347312858C49B001F2212 /* Utils.swift in Sources */, FDC346942858C412001F2212 /* Environment.swift in Sources */, @@ -2350,6 +2403,7 @@ FDC347402858C4B9001F2212 /* EFCLController-Extension.swift in Sources */, FDC346D22858C458001F2212 /* AppComponent.swift in Sources */, 1B5AFBAF2A52EFE600F777E1 /* Binding-Extension.swift in Sources */, + 1B0FFD7C2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, FDC346C42858C445001F2212 /* ConfigurableParameters.swift in Sources */, FDC346CD2858C458001F2212 /* Token.swift in Sources */, FDC346C32858C445001F2212 /* NotificationButton.swift in Sources */, @@ -2377,6 +2431,7 @@ FDC346D42858C458001F2212 /* SharedSettings.swift in Sources */, FDC346B62858C43F001F2212 /* OnboardingData.swift in Sources */, FDC346DC2858C458001F2212 /* NAError.swift in Sources */, + 1B0FFD452B20788E00E69392 /* Data-Extension.swift in Sources */, FDC346952858C413001F2212 /* EFCLController.swift in Sources */, FDC347322858C49B001F2212 /* Utils.swift in Sources */, FDC346962858C413001F2212 /* Environment.swift in Sources */, @@ -2400,6 +2455,7 @@ FD8A353D2863582600DA72CC /* EFCLController-Extension.swift in Sources */, FDC346DB2858C458001F2212 /* AppComponent.swift in Sources */, 1B5AFBB02A52EFE600F777E1 /* Binding-Extension.swift in Sources */, + 1B0FFD7D2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, FDC346C62858C445001F2212 /* ConfigurableParameters.swift in Sources */, FDC346D62858C458001F2212 /* Token.swift in Sources */, FDC346C52858C445001F2212 /* NotificationButton.swift in Sources */, @@ -2425,6 +2481,7 @@ 1B5AFB952A52EF9500F777E1 /* View-Extension.swift in Sources */, FDC346DD2858C459001F2212 /* SharedSettings.swift in Sources */, 1B5AFB382A52EE3C00F777E1 /* VideoAccessoryView.swift in Sources */, + 1BFAB6072AA85ABD009307C6 /* SlideShowView.swift in Sources */, FDC346BB2858C440001F2212 /* OnboardingData.swift in Sources */, 1B5AFB482A52EE3C00F777E1 /* PlayerView.swift in Sources */, FDC346E52858C459001F2212 /* NAError.swift in Sources */, @@ -2436,6 +2493,7 @@ FDC346E12858C459001F2212 /* UserReplyType.swift in Sources */, FD0D02D628D9F8AE00A167B7 /* SystemAlertController.swift in Sources */, FDC347292858C494001F2212 /* Decodable-Extensions.swift in Sources */, + 1B4B58CE2AF941BF0042A192 /* ViewSpec.swift in Sources */, 1B5AFB402A52EE3C00F777E1 /* MarkdownView.swift in Sources */, FDC3473E2858C4AF001F2212 /* InteractiveEFCLContoller.swift in Sources */, 1B5AFBC52A52FBD800F777E1 /* PopUpViewModel.swift in Sources */, @@ -2467,6 +2525,7 @@ FDC346C82858C446001F2212 /* ConfigurableParameters.swift in Sources */, FDC347282858C494001F2212 /* Int-Extension.swift in Sources */, FDC346DF2858C459001F2212 /* Token.swift in Sources */, + 1B0FFD462B20788E00E69392 /* Data-Extension.swift in Sources */, FDC3474A2858C4E8001F2212 /* AppDelegate.swift in Sources */, FDC3470F2858C48A001F2212 /* NoBackgroundScroller.swift in Sources */, 1B5AFBC22A52FBB900F777E1 /* PopUpView.swift in Sources */, @@ -2478,6 +2537,7 @@ 1B5AFB502A52EE3C00F777E1 /* AccessoryViewSource.swift in Sources */, 1B5AFB0A2A52ED8900F777E1 /* ACVDecoder.swift in Sources */, 1B5AFB052A52EC4400F777E1 /* SwiftUIButtonState.swift in Sources */, + 1B0FFD7E2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, FDC347252858C494001F2212 /* NSColor-Extension.swift in Sources */, FDC347242858C494001F2212 /* Notification-Extension.swift in Sources */, FDC346C72858C446001F2212 /* NotificationButton.swift in Sources */, @@ -2516,6 +2576,7 @@ FDC346E92858C459001F2212 /* TaskObject.swift in Sources */, 1B5AFB962A52EF9500F777E1 /* View-Extension.swift in Sources */, 1B5AFAFD2A52BD2F00F777E1 /* BackPanelController.swift in Sources */, + 1BFAB6082AA85ABD009307C6 /* SlideShowView.swift in Sources */, FDC346E62858C459001F2212 /* SharedSettings.swift in Sources */, 1B5AFB392A52EE3C00F777E1 /* VideoAccessoryView.swift in Sources */, FDC346C02858C440001F2212 /* OnboardingData.swift in Sources */, @@ -2527,6 +2588,7 @@ FDC347132858C48A001F2212 /* FlippedStackView.swift in Sources */, FDC346EA2858C459001F2212 /* UserReplyType.swift in Sources */, FD1730132875B82000781A69 /* DynamicNotificationButton.swift in Sources */, + 1B4B58CF2AF941BF0042A192 /* ViewSpec.swift in Sources */, FDC347142858C48A001F2212 /* HorizontalLine.swift in Sources */, FDC346992858C414001F2212 /* EFCLController.swift in Sources */, 1B5AFB412A52EE3C00F777E1 /* MarkdownView.swift in Sources */, @@ -2558,6 +2620,7 @@ FDC346C12858C440001F2212 /* NotificationObject.swift in Sources */, 1B5AFB592A52EE3C00F777E1 /* ProgressBarView.swift in Sources */, FDC3472E2858C495001F2212 /* String-Extension.swift in Sources */, + 1B0FFD472B20788E00E69392 /* Data-Extension.swift in Sources */, FDC3472D2858C495001F2212 /* NSScreen-Extension.swift in Sources */, FDC347502858C4F3001F2212 /* NotificationDispatch-Extension.swift in Sources */, FDC346ED2858C459001F2212 /* AppComponent.swift in Sources */, @@ -2569,6 +2632,7 @@ 1B5AFB512A52EE3C00F777E1 /* AccessoryViewSource.swift in Sources */, FDC346CA2858C446001F2212 /* ConfigurableParameters.swift in Sources */, FDC346E82858C459001F2212 /* Token.swift in Sources */, + 1B0FFD7F2B2078AD00E69392 /* ImageViewRepresentable.swift in Sources */, FDC346C92858C446001F2212 /* NotificationButton.swift in Sources */, FDC3473F2858C4AF001F2212 /* InteractiveEFCLContoller.swift in Sources */, 1B5AFB452A52EE3C00F777E1 /* HTMLView.swift in Sources */, @@ -2715,7 +2779,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2725,7 +2789,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.alert; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2745,7 +2809,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2755,7 +2819,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.alert; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2775,7 +2839,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2785,7 +2849,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.popup; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2805,7 +2869,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2815,7 +2879,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.popup; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2835,7 +2899,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2845,7 +2909,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.onboarding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2864,7 +2928,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2874,7 +2938,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.onboarding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2893,7 +2957,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2903,7 +2967,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.banner; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2923,7 +2987,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2933,7 +2997,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.banner; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2948,6 +3012,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -2978,12 +3043,13 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_TESTING_SEARCH_PATHS = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -2999,7 +3065,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -3013,6 +3079,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -3043,12 +3110,13 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTING_SEARCH_PATHS = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -3058,7 +3126,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -3076,7 +3144,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -3087,7 +3155,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3106,7 +3174,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -3117,7 +3185,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.3; + MARKETING_VERSION = 3.1.0; ONLY_ACTIVE_ARCH = NO; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3133,7 +3201,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3155,7 +3223,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3177,7 +3245,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3199,7 +3267,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3263,7 +3331,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3285,7 +3353,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3306,7 +3374,7 @@ buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3327,7 +3395,7 @@ buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3349,7 +3417,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3371,7 +3439,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_TESTING_SEARCH_PATHS = YES; @@ -3392,7 +3460,7 @@ buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; ENABLE_TESTING_SEARCH_PATHS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -3411,7 +3479,7 @@ buildSettings = { CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 108; + CURRENT_PROJECT_VERSION = 110; DEAD_CODE_STRIPPING = YES; ENABLE_TESTING_SEARCH_PATHS = YES; GENERATE_INFOPLIST_FILE = YES; diff --git a/Notification Agent.xcodeproj/xcshareddata/xcschemes/IBM Notifier Alert.xcscheme b/Notification Agent.xcodeproj/xcshareddata/xcschemes/IBM Notifier Alert.xcscheme index e5df50f..7ba7341 100644 --- a/Notification Agent.xcodeproj/xcshareddata/xcschemes/IBM Notifier Alert.xcscheme +++ b/Notification Agent.xcodeproj/xcshareddata/xcschemes/IBM Notifier Alert.xcscheme @@ -1,6 +1,6 @@ 3 else { + return false + } + let gifSignature = "GIF".data(using: .ascii) + return self.prefix(3) == gifSignature + } +} diff --git a/Shared/Extensions/Decodable-Extensions.swift b/Shared/Extensions/Decodable-Extensions.swift index 0edf0dd..410513f 100644 --- a/Shared/Extensions/Decodable-Extensions.swift +++ b/Shared/Extensions/Decodable-Extensions.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 22/01/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Extensions/EFCLController-Extension.swift b/Shared/Extensions/EFCLController-Extension.swift index 1cbd536..da02d15 100644 --- a/Shared/Extensions/EFCLController-Extension.swift +++ b/Shared/Extensions/EFCLController-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 8/26/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // @@ -24,6 +24,7 @@ extension EFCLController { } let taskObject = try JSONDecoder().decode(TaskObject.self, from: data) context.sharedSettings = taskObject.settings + context.disableQuit = taskObject.notification.disableQuit NotificationCenter.default.post(name: .showNotification, object: self, userInfo: ["object": taskObject.notification]) diff --git a/Shared/Extensions/Int-Extension.swift b/Shared/Extensions/Int-Extension.swift index 5b2999e..3ecedcd 100644 --- a/Shared/Extensions/Int-Extension.swift +++ b/Shared/Extensions/Int-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 8/10/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Extensions/NSColor-Extension.swift b/Shared/Extensions/NSColor-Extension.swift index 4cfae9c..8ea5cbc 100644 --- a/Shared/Extensions/NSColor-Extension.swift +++ b/Shared/Extensions/NSColor-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 15/04/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Extensions/NSScreen-Extension.swift b/Shared/Extensions/NSScreen-Extension.swift index e6af8d6..b41d0e8 100644 --- a/Shared/Extensions/NSScreen-Extension.swift +++ b/Shared/Extensions/NSScreen-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 27/04/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Extensions/Notification-Extension.swift b/Shared/Extensions/Notification-Extension.swift index d1aa81c..ed3eaef 100644 --- a/Shared/Extensions/Notification-Extension.swift +++ b/Shared/Extensions/Notification-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 7/10/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Extensions/String-Extension.swift b/Shared/Extensions/String-Extension.swift index d42903d..dcea0c7 100644 --- a/Shared/Extensions/String-Extension.swift +++ b/Shared/Extensions/String-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 8/10/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Extensions/View-Extension.swift b/Shared/Extensions/View-Extension.swift index 771fc84..a1e5934 100644 --- a/Shared/Extensions/View-Extension.swift +++ b/Shared/Extensions/View-Extension.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 06/02/23. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/Common/ACVDecoder.swift b/Shared/Model/Common/ACVDecoder.swift index a4e2132..00189d7 100644 --- a/Shared/Model/Common/ACVDecoder.swift +++ b/Shared/Model/Common/ACVDecoder.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 15/12/22. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -34,12 +34,12 @@ struct ACVDecoder { throw NAError.efclController(type: .invalidAccessoryViewPayload) } - var splittedStrings = payload.split(separator: "/") + var splittedStrings = payload.replacingOccurrences(of: "//", with: "/#escaping-double-slash /").split(separator: "/") guard splittedStrings.count > 0 else { throw NAError.efclController(type: .invalidAccessoryViewPayload) } splittedStrings.reverse() for index in 0.. CGSize { + switch self.mediaType { + case .image: + guard let image = self.image else { return .zero } + return image.size + case .video: + guard let size = self.videoResolution else { return .zero } + return size + } + } + + /// Returns the aspect ratio of the media + func aspectRatioForMedia() -> Double { + let resolution = resolutionForMedia() + return resolution != .zero ? resolution.width/resolution.height : 16/9 + } + + // MARK: - Private Methods + /// Get the resolution of the video. /// - Parameter url: url of the video. /// - Returns: the resolution of the video. diff --git a/Shared/Model/Common/PickerItem.swift b/Shared/Model/Common/PickerItem.swift index c2400a4..1bc916b 100644 --- a/Shared/Model/Common/PickerItem.swift +++ b/Shared/Model/Common/PickerItem.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 15/12/22. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/Common/SharedSettings.swift b/Shared/Model/Common/SharedSettings.swift index fa028bf..90fc247 100644 --- a/Shared/Model/Common/SharedSettings.swift +++ b/Shared/Model/Common/SharedSettings.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 22/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/Common/TaskObject.swift b/Shared/Model/Common/TaskObject.swift index a9166be..b23ed2a 100644 --- a/Shared/Model/Common/TaskObject.swift +++ b/Shared/Model/Common/TaskObject.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 22/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/Common/Token.swift b/Shared/Model/Common/Token.swift index abb6fd4..1d0b475 100644 --- a/Shared/Model/Common/Token.swift +++ b/Shared/Model/Common/Token.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Jan Valentik on 20/11/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/Common/UserReplyType.swift b/Shared/Model/Common/UserReplyType.swift index 2f89a52..5fddb14 100644 --- a/Shared/Model/Common/UserReplyType.swift +++ b/Shared/Model/Common/UserReplyType.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 17/06/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/UIObjects/ConfigurableParameters.swift b/Shared/Model/UIObjects/ConfigurableParameters.swift index f311c7a..d5abf31 100644 --- a/Shared/Model/UIObjects/ConfigurableParameters.swift +++ b/Shared/Model/UIObjects/ConfigurableParameters.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 9/10/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/UIObjects/DynamicNotificationButton.swift b/Shared/Model/UIObjects/DynamicNotificationButton.swift index 09d233a..b971c2e 100644 --- a/Shared/Model/UIObjects/DynamicNotificationButton.swift +++ b/Shared/Model/UIObjects/DynamicNotificationButton.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 23/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/UIObjects/NotificationAccessoryElement.swift b/Shared/Model/UIObjects/NotificationAccessoryElement.swift index a26758a..754c1e6 100644 --- a/Shared/Model/UIObjects/NotificationAccessoryElement.swift +++ b/Shared/Model/UIObjects/NotificationAccessoryElement.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 7/9/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // @@ -41,6 +41,7 @@ public class NotificationAccessoryElement: NSObject, Codable, NSSecureCoding { case htmlwhitebox case checklist case datepicker + case slideshow } // MARK: - Variables diff --git a/Shared/Model/UIObjects/NotificationButton.swift b/Shared/Model/UIObjects/NotificationButton.swift index 28fb802..ad9deea 100644 --- a/Shared/Model/UIObjects/NotificationButton.swift +++ b/Shared/Model/UIObjects/NotificationButton.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 7/9/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/UIObjects/NotificationObject.swift b/Shared/Model/UIObjects/NotificationObject.swift index d163498..2be3d85 100644 --- a/Shared/Model/UIObjects/NotificationObject.swift +++ b/Shared/Model/UIObjects/NotificationObject.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 7/9/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // // swiftlint:disable type_body_length file_length @@ -107,6 +107,12 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { var backgroundPanel: BackgroundPanelStyle? /// A boolean value that define if the UI should be movable for the user. var isMovable: Bool = true + /// A boolean value that define if the UI should ignore cmd+q shortcut. + var disableQuit: Bool = false + /// Custom width for the pop-up window size. + var customWidth: String? + /// A boolean value that defined if the UI should appear without any destructive CTA. + var buttonless: Bool = false // MARK: - Initializers @@ -243,12 +249,17 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { if let isNotMovable = dict["unmovable"] as? String { self.isMovable = !(isNotMovable.lowercased() == "true") } + if let disableQuit = dict["disable_quit"] as? String { + self.disableQuit = disableQuit.lowercased() == "true" + } + self.customWidth = dict["custom_width"] as? String + if let buttonless = dict["buttonless"] as? String { + self.buttonless = buttonless.lowercased() == "true" + } super.init() try checkObjectConsistency() } - - // swiftlint:enable function_body_length - + private func checkObjectConsistency() throws { switch type { case .popup, .banner, .alert, .systemalert: @@ -289,6 +300,23 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { resetCustomIconSize("Please check the format of -icon_height argument.") } } + func resetCustomSize(_ message: String) { + NALogger.shared.log("%{public}@", [message]) + customWidth = nil + } + if let customWidthAsString = customWidth { + if let customWidthNumber = NumberFormatter().number(from: customWidthAsString) { + let customWidth = CGFloat(truncating: customWidthNumber) + if let screenWidth = NSScreen.main?.visibleFrame.size.width, customWidth > screenWidth { + resetCustomSize("The desired window custom width exceed the current main display width.") + } + if customWidth < 520 { + resetCustomSize("It's not allowed to define window's custom width lower than the standard one.") + } + } else { + resetCustomSize("Please check the format of -custom_width argument.") + } + } case .onboarding: guard self.payload != nil || self.workflow != nil else { throw NAError.dataFormat(type: .invalidOnboardingPayload) @@ -296,6 +324,8 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { } } + // swiftlint:enable function_body_length + static func loadOnboardingPayload(_ payload: String) throws -> OnboardingData { if payload.isValidURL, let url = URL(string: payload) { return try OnboardingData(from: url) @@ -341,6 +371,9 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { case workflow case backgroundPanel case isMovable + case disableQuit + case customWidth + case buttonless } required public init(from decoder: Decoder) throws { @@ -356,8 +389,8 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { self.titleFontSize = try container.decodeIfPresent(String.self, forKey: .titleFontSize) self.subtitle = try container.decodeIfPresent(String.self, forKey: .subtitle) self.iconPath = try container.decodeIfPresent(String.self, forKey: .iconPath) - self.iconWidth = try container.decodeIfPresent( String.self, forKey: .iconWidth) - self.iconHeight = try container.decodeIfPresent( String.self, forKey: .iconHeight) + self.iconWidth = try container.decodeIfPresent(String.self, forKey: .iconWidth) + self.iconHeight = try container.decodeIfPresent(String.self, forKey: .iconHeight) self.notificationImage = try container.decodeIfPresent(String.self, forKey: .notificationAttachment) self.accessoryViews = try container.decodeIfPresent([NotificationAccessoryElement].self, forKey: .accessoryViews) self.mainButton = try container.decode(NotificationButton.self, forKey: .mainButton) @@ -385,6 +418,9 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { self.backgroundPanel = BackgroundPanelStyle(rawValue: backgroundPanelRawValue) } self.isMovable = try container.decode(Bool.self, forKey: .isMovable) + self.disableQuit = try container.decode(Bool.self, forKey: .disableQuit) + self.customWidth = try container.decodeIfPresent(String.self, forKey: .customWidth) + self.buttonless = try container.decode(Bool.self, forKey: .buttonless) } public func encode(to encoder: Encoder) throws { @@ -421,7 +457,9 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { try container.encodeIfPresent(self.workflow?.rawValue, forKey: .workflow) try container.encodeIfPresent(self.backgroundPanel?.rawValue, forKey: .backgroundPanel) try container.encodeIfPresent(self.isMovable, forKey: .isMovable) - + try container.encodeIfPresent(self.disableQuit, forKey: .disableQuit) + try container.encodeIfPresent(self.customWidth, forKey: .customWidth) + try container.encodeIfPresent(self.buttonless, forKey: .buttonless) } // MARK: Codable protocol conformity - END @@ -518,8 +556,15 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { if let backgroundPanelRawValue = self.backgroundPanel?.rawValue { coder.encode(backgroundPanelRawValue, forKey: NOCodingKeys.backgroundPanel.rawValue) } - let number = NSNumber(booleanLiteral: isMovable) - coder.encode(number, forKey: NOCodingKeys.isMovable.rawValue) + let nIsMovable = NSNumber(booleanLiteral: isMovable) + coder.encode(nIsMovable, forKey: NOCodingKeys.isMovable.rawValue) + let nDisableQuit = NSNumber(booleanLiteral: disableQuit) + coder.encode(nDisableQuit, forKey: NOCodingKeys.disableQuit.rawValue) + if let customWidth = self.customWidth { + coder.encode(customWidth, forKey: NOCodingKeys.customWidth.rawValue) + } + let nButtonless = NSNumber(booleanLiteral: buttonless) + coder.encode(nButtonless, forKey: NOCodingKeys.buttonless.rawValue) } // swiftlint:enable function_body_length @@ -562,6 +607,9 @@ public final class NotificationObject: NSObject, Codable, NSSecureCoding { self.backgroundPanel = BackgroundPanelStyle(rawValue: backgroundPanelRawValue as String) } self.isMovable = coder.decodeObject(of: NSNumber.self, forKey: NOCodingKeys.isMovable.rawValue) as? Bool ?? true + self.disableQuit = coder.decodeObject(of: NSNumber.self, forKey: NOCodingKeys.disableQuit.rawValue) as? Bool ?? false + self.customWidth = coder.decodeObject(of: NSString.self, forKey: NOCodingKeys.customWidth.rawValue) as String? + self.buttonless = coder.decodeObject(of: NSNumber.self, forKey: NOCodingKeys.buttonless.rawValue) as? Bool ?? false } // MARK: - NSSecureCoding protocol conformity - END diff --git a/Shared/Model/UIObjects/OnboardingData.swift b/Shared/Model/UIObjects/OnboardingData.swift index bc5f43b..e329327 100644 --- a/Shared/Model/UIObjects/OnboardingData.swift +++ b/Shared/Model/UIObjects/OnboardingData.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 21/01/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/UIObjects/ProgressState.swift b/Shared/Model/UIObjects/ProgressState.swift index a03232f..cf1d6d7 100644 --- a/Shared/Model/UIObjects/ProgressState.swift +++ b/Shared/Model/UIObjects/ProgressState.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 10/15/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/UIObjects/SwiftUIButtonState.swift b/Shared/Model/UIObjects/SwiftUIButtonState.swift index ed3bda0..845aa9b 100644 --- a/Shared/Model/UIObjects/SwiftUIButtonState.swift +++ b/Shared/Model/UIObjects/SwiftUIButtonState.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 16/01/23. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Model/UIObjects/ViewSpec.swift b/Shared/Model/UIObjects/ViewSpec.swift new file mode 100644 index 0000000..827df51 --- /dev/null +++ b/Shared/Model/UIObjects/ViewSpec.swift @@ -0,0 +1,32 @@ +// +// ViewSpec.swift +// Notification Agent +// +// Created by Simone Martorelli on 13/10/2023. +// Copyright © 2023 IBM. All rights reserved. +// SPDX-License-Identifier: Apache2.0 +// + +import SwiftUI + +/// ViewSpec is an observable object used as environment object that stores common useful information about the main view. +class ViewSpec: ObservableObject { + + // MARK: - Published Variables + + @Published var mainViewWidth: CGFloat + @Published var contentMode: ContentMode + @Published var iconSize: CGSize + + var accessoryViewWidth: CGFloat { + return mainViewWidth-iconSize.width-40 + } + + // MARK: - Initializers + + init(mainViewWidth: CGFloat, contentMode: ContentMode = .fill, iconSize: CGSize = CGSize(width: 60, height: 60)) { + self.mainViewWidth = mainViewWidth + self.contentMode = contentMode + self.iconSize = iconSize + } +} diff --git a/Shared/Protocols/ControlActionClosureProtocol.swift b/Shared/Protocols/ControlActionClosureProtocol.swift index cf68c55..ebd12b7 100644 --- a/Shared/Protocols/ControlActionClosureProtocol.swift +++ b/Shared/Protocols/ControlActionClosureProtocol.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 09/02/23. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // Credits: Sindre Sorhus (sindresorhus) // diff --git a/Shared/Protocols/InteractiveObjectProtocol.swift b/Shared/Protocols/InteractiveObjectProtocol.swift index ad27aee..938d301 100644 --- a/Shared/Protocols/InteractiveObjectProtocol.swift +++ b/Shared/Protocols/InteractiveObjectProtocol.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 24/06/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Resources/en.lproj/Localizable.strings b/Shared/Resources/en.lproj/Localizable.strings index 4d87af4..ee9422f 100644 --- a/Shared/Resources/en.lproj/Localizable.strings +++ b/Shared/Resources/en.lproj/Localizable.strings @@ -3,7 +3,7 @@ Notification Agent Created by Simone Martorelli on 8/10/20. - Copyright © 2021 IBM Inc. All rights reserved. + Copyright © 2021 IBM. All rights reserved. SPDX-License-Identifier: Apache2.0 */ @@ -12,6 +12,10 @@ // MARK: - Accessory views "accessory_view_timer_label" = "Please make a selection in %@"; +"accessory_view_slideshow_backward_button" = "Previous"; +"accessory_view_slideshow_forward_button" = "Next"; +"accessory_view_slideshow_forward_button_hint" = "A click on this button will show the next image"; +"accessory_view_slideshow_backward_button_hint" = "A click on this button will show the previous image"; // MARK: - Buttons "default_main_button_label" = "OK"; diff --git a/Shared/Utils/ActionTrampoline.swift b/Shared/Utils/ActionTrampoline.swift index ecd2585..514ca66 100644 --- a/Shared/Utils/ActionTrampoline.swift +++ b/Shared/Utils/ActionTrampoline.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 09/02/23. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // Credits: Sindre Sorhus (sindresorhus) // diff --git a/Shared/Utils/Utils.swift b/Shared/Utils/Utils.swift index 51d0c96..7872a38 100644 --- a/Shared/Utils/Utils.swift +++ b/Shared/Utils/Utils.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 9/24/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/AccessoryViews/AppKit/AccessoryView.swift b/Shared/Views/AccessoryViews/AppKit/AccessoryView.swift index 1073ec5..e2b451b 100644 --- a/Shared/Views/AccessoryViews/AppKit/AccessoryView.swift +++ b/Shared/Views/AccessoryViews/AppKit/AccessoryView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 03/05/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/AccessoryViews/AppKit/HTMLAccessoryView.swift b/Shared/Views/AccessoryViews/AppKit/HTMLAccessoryView.swift index 5211a1a..be3741d 100644 --- a/Shared/Views/AccessoryViews/AppKit/HTMLAccessoryView.swift +++ b/Shared/Views/AccessoryViews/AppKit/HTMLAccessoryView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 15/04/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/AccessoryViews/AppKit/MarkdownTextView.swift b/Shared/Views/AccessoryViews/AppKit/MarkdownTextView.swift index 448df76..fc3f839 100644 --- a/Shared/Views/AccessoryViews/AppKit/MarkdownTextView.swift +++ b/Shared/Views/AccessoryViews/AppKit/MarkdownTextView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 9/21/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // @@ -87,7 +87,7 @@ final class MarkdownTextView: AccessoryView { textView.isEditable = false textView.isSelectable = true textView.translatesAutoresizingMaskIntoConstraints = false - textView.setAccessibilityHidden(true) + textView.setAccessibilityIdentifier("markdown_accessory_view") scrollView = NSScrollView() scrollView.translatesAutoresizingMaskIntoConstraints = false @@ -114,7 +114,6 @@ final class MarkdownTextView: AccessoryView { textColor = .labelColor } self.setText(text) - self.identifier = NSUserInterfaceItemIdentifier("markdown_accessory_view") } required init?(coder: NSCoder) { diff --git a/Shared/Views/AccessoryViews/AppKit/VideoAccessoryView.swift b/Shared/Views/AccessoryViews/AppKit/VideoAccessoryView.swift index ee17a4f..f43dfb9 100644 --- a/Shared/Views/AccessoryViews/AppKit/VideoAccessoryView.swift +++ b/Shared/Views/AccessoryViews/AppKit/VideoAccessoryView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 9/30/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewSource.swift b/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewSource.swift index aed7d03..cd832a8 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewSource.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewSource.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 11/05/2023. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewWrapper.swift b/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewWrapper.swift index 2b48114..79c5cad 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewWrapper.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewWrapper.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 09/02/23. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -13,8 +13,12 @@ import RichText /// AccessoryViewWrapper is a struct that define a view that works as generic wrapper for all the available Accessory Views. struct AccessoryViewWrapper: View { - - // MARK: - Variables + + // MARK: - Environment Variables + + @EnvironmentObject var viewSpec: ViewSpec + + // MARK: - Variables var source: AccessoryViewSource var contentMode: ContentMode = .fill @@ -25,13 +29,17 @@ struct AccessoryViewWrapper: View { switch source.accessoryView.type { case .secureinput, .securedinput, .input: try? InputView(source.accessoryView.payload ?? "", output: source.$output, mainButtonState: source.$mainButtonState, secondaryButtonState: source.$secondaryButtonState, legacyType: source.accessoryView.type) - .accessibilityIdentifier(source.accessoryView.type == .input ? "input_accessory_view" : "secure_input_accessory_view") case .checklist, .dropdown: try? PickerView(source.accessoryView.payload ?? "", output: source.$output, mainButtonState: source.$mainButtonState, secondaryButtonState: source.$secondaryButtonState, legacyType: source.accessoryView.type) - .accessibilityIdentifier(source.accessoryView.type == .checklist ? "checklist_accessory_view" : "dropdown_whitebox_accessory_view") case .image, .video: - try? MediaView(source.accessoryView.payload ?? "", output: source.$output, mainButtonState: source.$mainButtonState, secondaryButtonState: source.$secondaryButtonState, legacyType: source.accessoryView.type, contentMode: contentMode) - .accessibilityIdentifier(source.accessoryView.type == .image ? "image_accessory_view" : "video_whitebox_accessory_view") + try? MediaView(source.accessoryView.payload ?? "", + output: source.$output, + mainButtonState: source.$mainButtonState, + secondaryButtonState: source.$secondaryButtonState, + legacyType: source.accessoryView.type, + contentMode: viewSpec.contentMode, + containerWidth: viewSpec.accessoryViewWidth) + .accessibilityIdentifier(source.accessoryView.type == .image ? "image_accessory_view" : "video_accessory_view") case .html, .htmlwhitebox: ZStack { if source.accessoryView.type == .htmlwhitebox { @@ -46,13 +54,13 @@ struct AccessoryViewWrapper: View { .fixedSize(horizontal: false, vertical: true) } case .whitebox: - MarkdownView(text: source.accessoryView.payload?.localized ?? "", drawsBackground: true) + MarkdownView(text: source.accessoryView.payload?.localized ?? "", drawsBackground: true, containerWidth: viewSpec.accessoryViewWidth) case .progressbar: try? ProgressBarView(viewModel: source.viewModel as? ProgressBarViewModel) - .accessibilityIdentifier("progressbar_accessory_view") case .datepicker: try? DatePickerView(source.accessoryView.payload ?? "", output: source.$output, mainButtonState: source.$mainButtonState, secondaryButtonState: source.$secondaryButtonState) - .accessibilityIdentifier("datepicker_accessory_view") + case .slideshow: + try? SlideShowView(source.accessoryView.payload ?? "") default: EmptyView() } diff --git a/Shared/Views/AccessoryViews/SwiftUI/DatePickerView.swift b/Shared/Views/AccessoryViews/SwiftUI/DatePickerView.swift index 3473c8f..308dd57 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/DatePickerView.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/DatePickerView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 24/05/2023. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -21,6 +21,8 @@ struct DatePickerView: View { case preselection case components case style + case startDate = "start_date" + case endDate = "end_date" } // MARK: - Private Variables @@ -30,6 +32,8 @@ struct DatePickerView: View { private var style: any DatePickerStyle private var components: DatePickerComponents private var initialDate: Date? + private var startDate: Date? + private var endDate: Date = Date(timeIntervalSinceNow: 3156600000) // ~100 years from now private var dateFormatter: DateFormatter { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" @@ -88,6 +92,14 @@ struct DatePickerView: View { } let somevalues = try decoder.decode(key: DatePickerCodingKeys.preselection, ofType: String.self, from: payload) initialDate = dateFormatter.date(from: output.wrappedValue.isEmpty ? somevalues : output.wrappedValue) ?? Date() + let selectedDateString = try decoder.decode(key: DatePickerCodingKeys.preselection, ofType: String.self, from: payload) + initialDate = dateFormatter.date(from: output.wrappedValue.isEmpty ? selectedDateString : output.wrappedValue) ?? Date() + let startDateString = try decoder.decode(key: DatePickerCodingKeys.startDate, ofType: String.self, from: payload) + startDate = dateFormatter.date(from: output.wrappedValue.isEmpty ? startDateString : output.wrappedValue) ?? Date() + let endDateString = try decoder.decode(key: DatePickerCodingKeys.endDate, ofType: String.self, from: payload) + if let date = dateFormatter.date(from: output.wrappedValue.isEmpty ? endDateString : output.wrappedValue) { + endDate = date + } } // MARK: - Views @@ -100,16 +112,29 @@ struct DatePickerView: View { .accessibilityIdentifier("datepicker_accessory_view_title") } HStack(spacing: 0) { - DatePicker("", selection: $selectionValue.onUpdate(evaluateButtonState), displayedComponents: components) - .customDatePickerStyle(style) - .labelsHidden() - .onAppear { - if let initialDate = initialDate { - self.selectionValue = initialDate + if let rangeStart = startDate { + DatePicker("", selection: $selectionValue.onUpdate(evaluateButtonState), in: rangeStart...endDate, displayedComponents: components) + .customDatePickerStyle(style) + .labelsHidden() + .onAppear { + if let initialDate = initialDate { + self.selectionValue = initialDate + } + evaluateButtonState() + } + .accessibilityIdentifier("datepicker_accessory_view_picker") + } else { + DatePicker("", selection: $selectionValue.onUpdate(evaluateButtonState), displayedComponents: components) + .customDatePickerStyle(style) + .labelsHidden() + .onAppear { + if let initialDate = initialDate { + self.selectionValue = initialDate + } + evaluateButtonState() } - evaluateButtonState() - } - .accessibilityIdentifier("datepicker_accessory_view_picker") + .accessibilityIdentifier("datepicker_accessory_view_picker") + } Spacer() } .padding(0) diff --git a/Shared/Views/AccessoryViews/SwiftUI/InputView.swift b/Shared/Views/AccessoryViews/SwiftUI/InputView.swift index e4ce30c..131c593 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/InputView.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/InputView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 10/01/23. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/AccessoryViews/SwiftUI/MediaView.swift b/Shared/Views/AccessoryViews/SwiftUI/MediaView.swift index 4337a6a..9497830 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/MediaView.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/MediaView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 27/01/23. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -22,6 +22,8 @@ struct MediaView: View { var media: NAMedia /// The desired content mode for the media. var contentMode: ContentMode + /// The width of the container view. + var containerWidth: CGFloat // MARK: - Binded Variables @@ -39,14 +41,16 @@ struct MediaView: View { mainButtonState: Binding, secondaryButtonState: Binding, legacyType: NotificationAccessoryElement.ViewType, - contentMode: ContentMode = .fill) throws { + contentMode: ContentMode = .fill, + containerWidth: CGFloat) throws { /// Initialize the binded variables. _output = output _mainButtonState = mainButtonState _secondaryButtonState = secondaryButtonState self.contentMode = contentMode - + self.containerWidth = containerWidth + /// Set the media view type. type = legacyType @@ -74,10 +78,17 @@ struct MediaView: View { case .image: /// If the media is an image, display the image using an Image view. if let image = media.image { - Image(nsImage: image) - .resizable() - .aspectRatio(aspectRatioForMedia(media), contentMode: contentMode) - .frame(maxWidth: .infinity, maxHeight: .infinity) + if media.isGIF { + ImageViewRepresentable(image: image, + width: containerWidth, + aspectRatio: aspectRatioForMedia(media), + contentMode: contentMode) + } else { + Image(nsImage: image) + .resizable() + .aspectRatio(aspectRatioForMedia(media), contentMode: contentMode) + .frame(maxWidth: .infinity, maxHeight: .infinity) + } } else { EmptyView() } @@ -129,6 +140,6 @@ struct MediaView_Previews: PreviewProvider { return .enabled }, set: { _, _ in - }), legacyType: .image) + }), legacyType: .image, containerWidth: 420) } } diff --git a/Shared/Views/AccessoryViews/SwiftUI/PickerView.swift b/Shared/Views/AccessoryViews/SwiftUI/PickerView.swift index 60d85f0..e5a7989 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/PickerView.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/PickerView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 24/11/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -122,7 +122,7 @@ struct PickerView: View { if !title.isEmpty { Text(title) .fixedSize() - .accessibilityIdentifier("picker_accessory_view_secure_title") + .accessibilityIdentifier("picker_accessory_view_title") } switch self.type { case .radiobuttons: @@ -144,6 +144,7 @@ struct PickerView: View { Text(element.label.wrappedValue).tag(element.id.wrappedValue.description).fixedSize(horizontal: false, vertical: true) } .toggleStyle(.checkbox) + .accessibilityIdentifier("picker_accessory_view_checkboxes_\(element.label.wrappedValue.trimmingCharacters(in: .whitespaces))") } } .onAppear { @@ -156,7 +157,6 @@ struct PickerView: View { } evaluateButtonState() } - .accessibilityIdentifier("picker_accessory_view_checkboxes") case .dropdown: Picker("", selection: self.$selectionValue.onUpdate(evaluateButtonState)) { Text(placeholder).tag("-1") diff --git a/Shared/Views/AccessoryViews/SwiftUI/ProgressBar/ProgressBarView.swift b/Shared/Views/AccessoryViews/SwiftUI/ProgressBar/ProgressBarView.swift index 4e29343..980b1ed 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/ProgressBar/ProgressBarView.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/ProgressBar/ProgressBarView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 17/03/23. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -41,7 +41,7 @@ struct ProgressBarView: View { .progressViewStyle(.linear) .padding(.top, 0) .padding(.bottom, 0) - .accessibilityIdentifier("progressbar_accessory_view_progressview_indetermined") + .accessibilityIdentifier("progressbar_accessory_view_progressview_indeterminate") } Text(viewModel.progressState.bottomMessage) .font(.system(.footnote)) diff --git a/Shared/Views/AccessoryViews/SwiftUI/ProgressBar/ProgressBarViewModel.swift b/Shared/Views/AccessoryViews/SwiftUI/ProgressBar/ProgressBarViewModel.swift index d1b2ccf..e0c5050 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/ProgressBar/ProgressBarViewModel.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/ProgressBar/ProgressBarViewModel.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 20/03/23. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/AccessoryViews/SwiftUI/SlideShowView.swift b/Shared/Views/AccessoryViews/SwiftUI/SlideShowView.swift new file mode 100644 index 0000000..f10626e --- /dev/null +++ b/Shared/Views/AccessoryViews/SwiftUI/SlideShowView.swift @@ -0,0 +1,175 @@ +// +// SlideShowView.swift +// Notification Agent +// +// Created by Simone Martorelli on 19/07/2023. +// Copyright © 2021 IBM. All rights reserved. +// SPDX-License-Identifier: Apache2.0 +// + +import SwiftUI +import Combine + +/// SlideShowView is a struct that define a view able to display multiple images as a slideshow. +struct SlideShowView: View { + + // MARK: - Support Enums + + enum SlideShowCodingKeys: String, AVCIterable { + case images + case autoplay + case delay + } + + // MARK: - Variables + + /// Boolean value to enable or disable the automatic images scrolling. + var autoplay: Bool + /// The array of images to be shown. + var images: [NAMedia] + /// Delay for the autoplay in seconds. + var delay: Int + /// The lower aspect ration between the loaded media. + var minAspectRatio: Double + /// The autoplay timer. + var timer: Publishers.Autoconnect? + + // MARK: - State variables + + /// Current selection. + @State private var selection: Int = 0 + + // MARK: - Initializers + + init(_ payload: String) throws { + let decoder = ACVDecoder(codingKeys: SlideShowCodingKeys.self) + let imagesURLRaw = try decoder.decode(key: SlideShowCodingKeys.images, ofType: String.self, from: payload) + autoplay = try decoder.decode(key: SlideShowCodingKeys.autoplay, ofType: Bool.self, from: payload) + delay = try decoder.decode(key: SlideShowCodingKeys.delay, ofType: Int.self, from: payload) + let imagesURL = imagesURLRaw.lines + images = [] + minAspectRatio = 1 + for imageURL in imagesURL { + if let media = NAMedia(type: .image, from: imageURL) { + images.append(media) + minAspectRatio = min(minAspectRatio, max(media.aspectRatioForMedia(), 1)) + } + } + guard images.count != 0 else { + throw NAError.dataFormat(type: .invalidSlideShowPayload) + } + if autoplay { + timer = Timer.publish(every: Double(max(delay, 3)), on: .main, in: .default).autoconnect() + } + } + + // MARK: - Views + + var body: some View { + ZStack { + if let image = images[selection].image { + if AppComponent.current == .popup { + Image(nsImage: image) + .resizable() + .aspectRatio(images[selection].aspectRatioForMedia(), contentMode: .fit) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .fixedSize(horizontal: false, vertical: true) + .accessibilityIdentifier("accessory_view_slideshow_image") + } else { + Image(nsImage: image) + .resizable() + .aspectRatio(images[selection].aspectRatioForMedia(), contentMode: .fit) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .padding(EdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 0)) + .accessibilityIdentifier("accessory_view_slideshow_image") + } + } + HStack(alignment: .center) { + if selection != 0 { + Button { + selection -= 1 + invalidateTimer() + } label: { + Image(systemName: "chevron.left.square.fill") + .resizable() + } + .buttonStyle(.borderless) + .disabled(selection == 0) + .frame(width: 30, height: 30) + .shadow(color: Utils.currentInterfaceStyle == .light ? .white : .black, radius: 16) + .padding() + .accessibilityIdentifier("accessory_view_slideshow_backward_button") + .accessibilityLabel("accessory_view_slideshow_backward_button".localized) + .accessibilityHint("accessory_view_slideshow_backward_button_hint".localized) + } + Spacer() + if selection != images.count-1 { + Button { + selection += 1 + invalidateTimer() + } label: { + Image(systemName: "chevron.right.square.fill") + .resizable() + } + .buttonStyle(.borderless) + .disabled(selection == images.count-1) + .frame(width: 30, height: 30) + .shadow(color: Utils.currentInterfaceStyle == .light ? .white : .black, radius: 16) + .padding() + .accessibilityIdentifier("accessory_view_slideshow_forward_button") + .accessibilityLabel("accessory_view_slideshow_forward_button".localized) + .accessibilityHint("accessory_view_slideshow_forward_button_hint".localized) + } + } + if images.count > 1 { + VStack(alignment: .center) { + Spacer() + HStack(alignment: .center) { + ForEach(0..) -> NSImageView { + let imageView = NSImageView() + imageView.image = image + imageView.imageScaling = .scaleProportionallyUpOrDown + imageView.translatesAutoresizingMaskIntoConstraints = false + switch contentMode { + case .fit: + imageView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) + imageView.setContentCompressionResistancePriority(.defaultLow, for: .vertical) + imageView.widthAnchor.constraint(lessThanOrEqualToConstant: width).isActive = true + imageView.heightAnchor.constraint(lessThanOrEqualToConstant: width/aspectRatio).isActive = true + case .fill: + imageView.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal) + imageView.setContentCompressionResistancePriority(.defaultHigh, for: .vertical) + imageView.widthAnchor.constraint(equalToConstant: width).isActive = true + imageView.heightAnchor.constraint(equalToConstant: width/aspectRatio).isActive = true + } + return imageView + } + + func updateNSView(_ nsView: NSImageView, context: NSViewRepresentableContext) { + nsView.image = image + } +} diff --git a/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/MarkdownView.swift b/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/MarkdownView.swift index 72cd854..acbc3ae 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/MarkdownView.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/MarkdownView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 22/11/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/PlayerView.swift b/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/PlayerView.swift index c7cc607..5b4b240 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/PlayerView.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/PlayerView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 10/05/2023. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/Buttons/CircleButton.swift b/Shared/Views/Buttons/CircleButton.swift index acebc89..3e858e3 100644 --- a/Shared/Views/Buttons/CircleButton.swift +++ b/Shared/Views/Buttons/CircleButton.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 22/11/22. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/Buttons/NativeButton.swift b/Shared/Views/Buttons/NativeButton.swift index 06deaad..5215737 100644 --- a/Shared/Views/Buttons/NativeButton.swift +++ b/Shared/Views/Buttons/NativeButton.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 21/11/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // Credits: Sindre Sorhus (sindresorhus) // diff --git a/Shared/Views/Buttons/StandardButton.swift b/Shared/Views/Buttons/StandardButton.swift index 6f99e56..b4f4f4c 100644 --- a/Shared/Views/Buttons/StandardButton.swift +++ b/Shared/Views/Buttons/StandardButton.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 22/11/22. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/Common/BackPanelWindow.swift b/Shared/Views/Common/BackPanelWindow.swift index 817137b..8dbff97 100644 --- a/Shared/Views/Common/BackPanelWindow.swift +++ b/Shared/Views/Common/BackPanelWindow.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 19/05/2023. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/Common/FlippedStackView.swift b/Shared/Views/Common/FlippedStackView.swift index a00c3b3..272f310 100644 --- a/Shared/Views/Common/FlippedStackView.swift +++ b/Shared/Views/Common/FlippedStackView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 01/05/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/Common/HorizontalLine.swift b/Shared/Views/Common/HorizontalLine.swift index f92ff0f..8ed40d4 100644 --- a/Shared/Views/Common/HorizontalLine.swift +++ b/Shared/Views/Common/HorizontalLine.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 3/17/20. -// Copyright © 2021 IBM Inc. All rights reserved +// Copyright © 2021 IBM. All rights reserved // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/Common/NoBackgroundScroller.swift b/Shared/Views/Common/NoBackgroundScroller.swift index 9a84e7b..f01bae1 100644 --- a/Shared/Views/Common/NoBackgroundScroller.swift +++ b/Shared/Views/Common/NoBackgroundScroller.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 30/04/2021. -// Copyright © 2021 IBM Inc. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // diff --git a/Shared/Views/Components/Icon.swift b/Shared/Views/Components/Icon.swift index 46e974c..45c0d81 100644 --- a/Shared/Views/Components/Icon.swift +++ b/Shared/Views/Components/Icon.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 22/11/22. -// Copyright © 2022 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 //