From a961fdc95c87f4213a32fde8c71e6b8458965fc3 Mon Sep 17 00:00:00 2001 From: Simone Martorelli Date: Tue, 5 Sep 2023 11:28:40 +0200 Subject: [PATCH] fix(onboarding): multiple fixes to the onboarding ui and html av --- .sonarcloud.properties | 2 +- ATTRIBUTIONS.md | 431 ++++++++++++++++++ .../Resources/ATTRIBUTIONS.md | 431 ++++++++++++++++++ .../Views/OnboardingView.swift | 7 +- .../Views/OnboardingViewModel.swift | 10 +- .../Views/PageView.swift | 9 +- Notification Agent.xcodeproj/project.pbxproj | 84 ++-- README.md | 2 +- Shared/Model/Common/InfoSection.swift | 6 +- .../AppKit/HTMLAccessoryView.swift | 8 +- .../SwiftUI/AccessoryViewWrapper.swift | 14 +- .../SwiftUI/ViewRepresentable/HTMLView.swift | 8 +- Shared/Views/Components/InfoSectionView.swift | 152 ++++-- 13 files changed, 1067 insertions(+), 97 deletions(-) create mode 100644 ATTRIBUTIONS.md create mode 100644 Notification Agent Core/Resources/ATTRIBUTIONS.md diff --git a/.sonarcloud.properties b/.sonarcloud.properties index 753d807..709f132 100644 --- a/.sonarcloud.properties +++ b/.sonarcloud.properties @@ -1,6 +1,6 @@ # Python version (for python projects only) sonar.python.version=3 # Project Version to be used as Code Definition -sonar.projectVersion=3.0.0.104 +sonar.projectVersion=3.0.2.107 # Folders excluded from the scan sonar.exclusions=**/Notification Agent Core Tests/**,**/Notification Agent Alert Tests/**,**/Notification Agent Banner Tests/**,**/Notification Agent Popup Tests/**,**/Notification Agent Onboarding Tests/**,**/Notification Agent Popup UI Tests/**,**/Notification Agent Onboarding UI Tests/**,**/Notification Agent Core/Controllers/HelpBuilder.swift** diff --git a/ATTRIBUTIONS.md b/ATTRIBUTIONS.md new file mode 100644 index 0000000..c39ab96 --- /dev/null +++ b/ATTRIBUTIONS.md @@ -0,0 +1,431 @@ +# IBM Notifier Attributions + +IBM Notifier makes use of code from some other projects. +Listed below are notable sections of code that are licensed from other projects and the relevant license of those projects. + +Projects: + +- [RichText](https://github.com/NuPlay/RichText): used to represent html code as attributed text - [LICENSE](#richtext) +- [BlueSignals](https://github.com/Kitura/BlueSignals): used for catching system signals - [LICENSE](#bluesignals) +- [SwiftyMarkdown](https://github.com/SimonFairbairn/SwiftyMarkdown): used to represent markdown as attributed text on macOS 11 Big Sur - [LICENSE](#swiftymarkdown) +- [Swift-JWT](https://github.com/Kitura/Swift-JWT): used to generate JWT in Swift - [LICENSE](#swift-jwt) + + +If you believe there is an error or omission in this list please open an issue about it and we'll fix it. + +## Licenses + +### RichText + +```text +MIT License + +Copyright (c) 2021 NuPlay + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + +### BlueSignals + +```text + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +``` + +### SwiftyMarkdown + +```text +The MIT License (MIT) + +Copyright (c) 2016 Simon Fairbairn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + +### Swift-JWT + +```text + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +``` \ No newline at end of file diff --git a/Notification Agent Core/Resources/ATTRIBUTIONS.md b/Notification Agent Core/Resources/ATTRIBUTIONS.md new file mode 100644 index 0000000..51bc37f --- /dev/null +++ b/Notification Agent Core/Resources/ATTRIBUTIONS.md @@ -0,0 +1,431 @@ +# IBM Notifier Attributions + +IBM Notifier makes use of code from some other projects. +Listed below are notable sections of code that are licensed from other projects and the relevant license of those projects. + +Projects: + +- [RichText](https://github.com/NuPlay/RichText): used to represent html code as attributed text - [LICENSE](#richtext) +- [BlueSignals](https://github.com/Kitura/BlueSignals): used for catching system signals - [LICENSE](#bluesignals) +- [SwiftyMarkdown](https://github.com/SimonFairbairn/SwiftyMarkdown): used to represent markdown as attributed text on macOS 11 Big Sur - [LICENSE](#swiftymarkdown) +- [Swift-JWT](https://github.com/Kitura/Swift-JWT): used to generate JWT in Swift - [LICENSE](#swift-jwt) + + +If you believe there is an error or omission in this list please open an issue about it and we'll fix it. + +## Licenses + +### RichText + +```text +MIT License + +Copyright (c) 2021 NuPlay + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + +### BlueSignals + +```text + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +``` + +### SwiftyMarkdown + +```text +The MIT License (MIT) + +Copyright (c) 2016 Simon Fairbairn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + +### Swift-JWT + +```text + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +``` diff --git a/Notification Agent Onboarding/Views/OnboardingView.swift b/Notification Agent Onboarding/Views/OnboardingView.swift index b044da8..21783d6 100644 --- a/Notification Agent Onboarding/Views/OnboardingView.swift +++ b/Notification Agent Onboarding/Views/OnboardingView.swift @@ -27,9 +27,7 @@ struct OnboardingView: View { currentPage .accessibilityElement(children: .contain) Spacer() - Rectangle() - .frame(height: 0.5) - .foregroundColor(Color(.darkGray)) + Divider() HStack { HStack { if let infoSection = viewModel.currentPage.infoSection { @@ -87,6 +85,7 @@ struct OnboardingView: View { } .padding() } + .frame(maxWidth: 832, maxHeight: 600) } var currentPage: some View { @@ -95,7 +94,7 @@ struct OnboardingView: View { outp: $viewModel.pageOutputs, primaryButtonState: $viewModel.primaryButtonState, secondaryButtonState: $viewModel.secondaryButtonState)) - .padding() + .padding([.trailing, .leading, .top], 8) } } diff --git a/Notification Agent Onboarding/Views/OnboardingViewModel.swift b/Notification Agent Onboarding/Views/OnboardingViewModel.swift index fc59c41..141acb0 100644 --- a/Notification Agent Onboarding/Views/OnboardingViewModel.swift +++ b/Notification Agent Onboarding/Views/OnboardingViewModel.swift @@ -51,7 +51,7 @@ class OnboardingViewModel: NSObject, ObservableObject { if let page = onboardingData.pages[safe: currentIndex] { primaryButtonState = .enabled secondaryButtonState = .enabled - primaryButtonLabel = page.primaryButtonLabel ?? (isLastPage ? "onboarding_page_close_button".localized : "onboarding_page_continue_button".localized) + primaryButtonLabel = page.primaryButtonLabel ?? (isLastPage ? "onboarding_page_close_button".localized : "onboarding_page_continue_button".localized) secondaryButtonLabel = page.secondaryButtonLabel ?? "onboarding_page_back_button".localized currentPage = page guard currentIndex < outputsStore.count && currentIndex < inputsStore.count else { return } @@ -86,7 +86,7 @@ class OnboardingViewModel: NSObject, ObservableObject { self.currentPage = firstPage self.isLastPage = onboardingData.pages.count == 1 self.hideBackButton = true - self.primaryButtonLabel = firstPage.primaryButtonLabel ?? "onboarding_page_continue_button".localized + self.primaryButtonLabel = firstPage.primaryButtonLabel ?? (onboardingData.pages.count == 1 ? "onboarding_page_close_button".localized : "onboarding_page_continue_button".localized) self.secondaryButtonLabel = firstPage.secondaryButtonLabel ?? "onboarding_page_back_button".localized let tempMatrixArray: [[[String]]] = onboardingData.pages.map { page in guard page.isValidPage() else { @@ -111,7 +111,7 @@ class OnboardingViewModel: NSObject, ObservableObject { self.setTimeout(timeout) } NotificationCenter.default.addObserver(self, selector: #selector(repositionWindow), name: NSApplication.didChangeScreenParametersNotification, object: nil) - if let progressBarPayload = onboardingData.progressBarPayload { + if let progressBarPayload = onboardingData.progressBarPayload, onboardingData.pages.count > 1 { var payload: String = "/percent 0 /user_interaction_enabled true" if progressBarPayload.lowercased() == "automatic" { automaticProgressBar = true @@ -141,12 +141,14 @@ class OnboardingViewModel: NSObject, ObservableObject { resetTimers() switch type { case .main: - writeStoreOnDevice() if currentIndex >= (onboardingData.pages.count - 1) { + outputsStore[currentIndex] = self.pageOutputs + writeStoreOnDevice() Utils.applicationExit(withReason: .userFinishedOnboarding) } else { currentIndex += 1 } + writeStoreOnDevice() updateProgressBarIfNeeded() case .secondary: guard currentIndex > 0 else { return } diff --git a/Notification Agent Onboarding/Views/PageView.swift b/Notification Agent Onboarding/Views/PageView.swift index f7a4091..823212f 100644 --- a/Notification Agent Onboarding/Views/PageView.swift +++ b/Notification Agent Onboarding/Views/PageView.swift @@ -53,7 +53,7 @@ struct PageView: View { Text(title) .font(.bold(.title)()) .multilineTextAlignment(.center) - .padding(.top, 6) + .padding(.top, 12) .padding(.bottom, 4) .accessibilityAddTraits(.isHeader) .accessibilityIdentifier("onboarding_title") @@ -62,7 +62,6 @@ struct PageView: View { if let subtitle = viewModel.page.subtitle { Text(AttributedString(markdownText(subtitle).attributedString())) .multilineTextAlignment(.center) - .font(.title3) .accessibilityAddTraits(.isHeader) .accessibilityIdentifier("onboarding_subtitle") } @@ -76,7 +75,7 @@ struct PageView: View { if let subtitle = viewModel.page.subtitle { Text(subtitle) .multilineTextAlignment(.center) - .font(.title3) + .font(.title2) .accessibilityAddTraits(.isHeader) .accessibilityIdentifier("onboarding_subtitle") } @@ -90,9 +89,9 @@ struct PageView: View { } if !viewModel.accessoryViewsMatrix.isEmpty { - VStack { + VStack(alignment: .center) { ForEach(viewModel.accessoryViewsMatrix, id: \.hashValue) { row in - HStack { + HStack(alignment: .top) { ForEach(row, id: \.hashValue) { accessoryView in accessoryView } diff --git a/Notification Agent.xcodeproj/project.pbxproj b/Notification Agent.xcodeproj/project.pbxproj index 1fb892d..6dfdcb8 100644 --- a/Notification Agent.xcodeproj/project.pbxproj +++ b/Notification Agent.xcodeproj/project.pbxproj @@ -171,6 +171,8 @@ 1B5AFBCE2A52FC8400F777E1 /* PageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B5AFBCC2A52FC8400F777E1 /* PageView.swift */; }; 1B5AFBD02A52FC9800F777E1 /* PageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B5AFBCF2A52FC9800F777E1 /* PageViewModel.swift */; }; 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 */; }; 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 */; }; @@ -775,6 +777,7 @@ 1B5AFBC92A52FC7100F777E1 /* OnboardingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewModel.swift; sourceTree = ""; }; 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 = ""; }; 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 = ""; }; @@ -895,6 +898,7 @@ buildActionMask = 2147483647; files = ( B9B9014C26988A6200825FB1 /* Signals in Frameworks */, + 1BFAB6012AA7248C009307C6 /* RichText in Frameworks */, B961A503267A498200657930 /* SwiftyMarkdown in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -904,6 +908,7 @@ buildActionMask = 2147483647; files = ( B961A603267B8E2A00657930 /* SwiftyMarkdown in Frameworks */, + 1BFAB6032AA72496009307C6 /* RichText in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1295,6 +1300,7 @@ isa = PBXGroup; children = ( B9B4E20C26E8AEA1001D2D89 /* NOTICES.rtf */, + 1BFAB5FF2A9F281C009307C6 /* ATTRIBUTIONS.md */, B9B4E20D26E8AEA2001D2D89 /* PRIVACY POLICY.rtf */, B9B4E20E26E8AEA2001D2D89 /* TERMS AND CONDITIONS.rtf */, ); @@ -1505,6 +1511,7 @@ packageProductDependencies = ( B961A502267A498200657930 /* SwiftyMarkdown */, B9B9014B26988A6200825FB1 /* Signals */, + 1BFAB6002AA7248C009307C6 /* RichText */, ); productName = "Notification Agent Popups"; productReference = B961A4E02678F4F400657930 /* IBM Notifier Popup.app */; @@ -1525,6 +1532,7 @@ name = "IBM Notifier Onboarding"; packageProductDependencies = ( B961A602267B8E2A00657930 /* SwiftyMarkdown */, + 1BFAB6022AA72496009307C6 /* RichText */, ); productName = "Notification Agent Onboarding"; productReference = B961A542267A4E5200657930 /* IBM Notifier Onboarding.app */; @@ -1774,7 +1782,7 @@ B9B1720124F6C28800DF656A /* XCRemoteSwiftPackageReference "BlueSignals" */, B9A1425625D68DC500E87AD6 /* XCRemoteSwiftPackageReference "Swift-JWT" */, B97F10C225DD682900E15245 /* XCRemoteSwiftPackageReference "SwiftyMarkdown" */, - B9BC86212626D865000C9DBD /* XCRemoteSwiftPackageReference "KeychainAccess" */, + 1BFAB5F72A9F2378009307C6 /* XCRemoteSwiftPackageReference "RichText" */, ); productRefGroup = F47F5537249B8C1B006A0754 /* Products */; projectDirPath = ""; @@ -2707,7 +2715,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2717,7 +2725,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.alert; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2737,7 +2745,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2747,7 +2755,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.alert; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2767,7 +2775,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2777,7 +2785,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.popup; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2797,7 +2805,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2807,7 +2815,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.popup; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2827,7 +2835,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2837,7 +2845,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.onboarding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2856,7 +2864,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2866,7 +2874,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.onboarding; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2885,7 +2893,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2895,7 +2903,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.banner; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2915,7 +2923,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -2925,7 +2933,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier.banner; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2970,7 +2978,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -2991,7 +2999,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -3035,7 +3043,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -3050,7 +3058,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -3068,7 +3076,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -3079,7 +3087,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3098,7 +3106,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 104; + CURRENT_PROJECT_VERSION = 107; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -3109,7 +3117,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 3.0.0; + MARKETING_VERSION = 3.0.2; ONLY_ACTIVE_ARCH = NO; PRODUCT_BUNDLE_IDENTIFIER = com.ibm.cio.notifier; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3542,6 +3550,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 1BFAB5F72A9F2378009307C6 /* XCRemoteSwiftPackageReference "RichText" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/NuPlay/RichText.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.0.0; + }; + }; B97F10C225DD682900E15245 /* XCRemoteSwiftPackageReference "SwiftyMarkdown" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/SimonFairbairn/SwiftyMarkdown"; @@ -3566,17 +3582,19 @@ minimumVersion = 2.0.1; }; }; - B9BC86212626D865000C9DBD /* XCRemoteSwiftPackageReference "KeychainAccess" */ = { - isa = XCRemoteSwiftPackageReference; - repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess.git"; - requirement = { - kind = upToNextMajorVersion; - minimumVersion = 4.2.2; - }; - }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 1BFAB6002AA7248C009307C6 /* RichText */ = { + isa = XCSwiftPackageProductDependency; + package = 1BFAB5F72A9F2378009307C6 /* XCRemoteSwiftPackageReference "RichText" */; + productName = RichText; + }; + 1BFAB6022AA72496009307C6 /* RichText */ = { + isa = XCSwiftPackageProductDependency; + package = 1BFAB5F72A9F2378009307C6 /* XCRemoteSwiftPackageReference "RichText" */; + productName = RichText; + }; B961A502267A498200657930 /* SwiftyMarkdown */ = { isa = XCSwiftPackageProductDependency; package = B97F10C225DD682900E15245 /* XCRemoteSwiftPackageReference "SwiftyMarkdown" */; diff --git a/README.md b/README.md index 7d33fb7..062dcab 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![License](https://img.shields.io/badge/license-Apache%202-1984E5) ![Swift version](https://img.shields.io/badge/swift-5.8.1-1984E5) ![Xcode version](https://img.shields.io/badge/xcode-14.3.1-1984E5) -![Project version](https://img.shields.io/badge/version-3.0.0-1984E5) +![Project version](https://img.shields.io/badge/version-3.0.2-1984E5) ![macOS](https://img.shields.io/badge/os-macOS%2011+-bright%20green) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5823/badge)](https://bestpractices.coreinfrastructure.org/projects/5823) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=IBM_mac-ibm-notifications&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=IBM_mac-ibm-notifications) diff --git a/Shared/Model/Common/InfoSection.swift b/Shared/Model/Common/InfoSection.swift index 5a2767b..3d69a48 100644 --- a/Shared/Model/Common/InfoSection.swift +++ b/Shared/Model/Common/InfoSection.swift @@ -11,13 +11,13 @@ import Foundation /// A single info field struct InfoField: Codable, Identifiable { - var id: String + var id: UUID var label: String var description: String? var iconName: String? init(label: String, description: String? = nil, iconName: String? = nil) { - self.id = label + "\(description ?? "")" + self.id = UUID() self.label = label self.description = description self.iconName = iconName @@ -42,7 +42,7 @@ struct InfoField: Codable, Identifiable { let container = try decoder.container(keyedBy: CodingKeys.self) self.label = try container.decode(String.self, forKey: .label) self.description = try container.decodeIfPresent(String.self, forKey: .description) - self.id = label + "\(description ?? "")" + self.id = UUID() self.iconName = try container.decodeIfPresent(String.self, forKey: .iconName) } } diff --git a/Shared/Views/AccessoryViews/AppKit/HTMLAccessoryView.swift b/Shared/Views/AccessoryViews/AppKit/HTMLAccessoryView.swift index 6cbe6e0..5211a1a 100644 --- a/Shared/Views/AccessoryViews/AppKit/HTMLAccessoryView.swift +++ b/Shared/Views/AccessoryViews/AppKit/HTMLAccessoryView.swift @@ -21,6 +21,7 @@ final class HTMLAccessoryView: AccessoryView { return _containerWidth ?? (self.superview?.bounds.width ?? 0) } private var scrollViewHeightAnchor: NSLayoutConstraint! + private var scrollViewWidthAnchor: NSLayoutConstraint! private var textViewWidthAnchor: NSLayoutConstraint! private var textViewHeightAnchor: NSLayoutConstraint! private var context = Context.main @@ -128,6 +129,9 @@ final class HTMLAccessoryView: AccessoryView { scrollViewHeightAnchor?.isActive = false scrollViewHeightAnchor = scrollView.heightAnchor.constraint(equalToConstant: scrollViewHeight) scrollViewHeightAnchor?.isActive = true + scrollViewWidthAnchor?.isActive = false + scrollViewWidthAnchor = scrollView.widthAnchor.constraint(equalToConstant: containerWidth) + scrollViewWidthAnchor?.isActive = true textViewWidthAnchor?.isActive = false textViewWidthAnchor = textView.widthAnchor.constraint(equalToConstant: max(containerWidth-12, 0)) textViewWidthAnchor?.isActive = true @@ -138,10 +142,6 @@ final class HTMLAccessoryView: AccessoryView { textView.textContainer?.size = CGSize(width: textViewSize.width-12, height: textViewSize.height) } - override func configureAccessibilityElements() { - - } - // MARK: - Private Methods /// Translate the html string in a Swift attributed string. diff --git a/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewWrapper.swift b/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewWrapper.swift index a0d3ef2..2b48114 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewWrapper.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/AccessoryViewWrapper.swift @@ -9,6 +9,7 @@ import SwiftUI import Combine +import RichText /// AccessoryViewWrapper is a struct that define a view that works as generic wrapper for all the available Accessory Views. struct AccessoryViewWrapper: View { @@ -32,7 +33,18 @@ struct AccessoryViewWrapper: View { 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") case .html, .htmlwhitebox: - HTMLView(text: source.accessoryView.payload ?? "", drawsBackground: source.accessoryView.type == .htmlwhitebox || source.accessoryView.type == .whitebox) + ZStack { + if source.accessoryView.type == .htmlwhitebox { + Color.white + } + ScrollView { + RichText(html: source.accessoryView.payload ?? "") + .colorScheme(source.accessoryView.type == .htmlwhitebox ? .light : .auto) + .padding(source.accessoryView.type == .htmlwhitebox ? 4 : 0) + } + .frame(maxHeight: AppComponent.current == .popup ? 300 : .infinity) + .fixedSize(horizontal: false, vertical: true) + } case .whitebox: MarkdownView(text: source.accessoryView.payload?.localized ?? "", drawsBackground: true) case .progressbar: diff --git a/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/HTMLView.swift b/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/HTMLView.swift index dd20d2a..cd071c1 100644 --- a/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/HTMLView.swift +++ b/Shared/Views/AccessoryViews/SwiftUI/ViewRepresentable/HTMLView.swift @@ -26,12 +26,12 @@ struct HTMLView: NSViewRepresentable { var containerWidth: CGFloat? // MARK: - Protocol Methods - + func makeNSView(context: NSViewRepresentableContext) -> HTMLAccessoryView { let markdownTextView = HTMLAccessoryView(withText: text, - drawsBackground: drawsBackground ?? false, - maxViewHeight: maxViewHeight ?? 300, - containerWidth: containerWidth ?? 400) + drawsBackground: drawsBackground ?? false, + maxViewHeight: maxViewHeight ?? 300, + containerWidth: containerWidth ?? 400) return markdownTextView } diff --git a/Shared/Views/Components/InfoSectionView.swift b/Shared/Views/Components/InfoSectionView.swift index a1a7198..8ceb78f 100644 --- a/Shared/Views/Components/InfoSectionView.swift +++ b/Shared/Views/Components/InfoSectionView.swift @@ -3,7 +3,7 @@ // Notification Agent // // Created by Simone Martorelli on 04/04/2023. -// Copyright © 2023 IBM. All rights reserved. +// Copyright © 2021 IBM. All rights reserved. // SPDX-License-Identifier: Apache2.0 // @@ -29,70 +29,99 @@ struct InfoSectionView: View { } return size } + var contentSize: CGSize + + // MARK: - Initializers + + init(section: InfoSection) { + self.section = section + self.contentSize = Self.calculateIdealSize(for: section) + } // MARK: - Views var body: some View { - ScrollView { - VStack(alignment: .leading, spacing: 10) { - ForEach(section.fields) { field in - HStack { - if let description = field.description { - Text(field.label) - .font(.body) - .frame(maxWidth: 80, maxHeight: .infinity, alignment: .leading) - Divider() - .padding(.horizontal) - Text(description) - .font(.body) - } else { - Text(field.label) - .font(.body) - .frame(alignment: .leading) - } + if contentSize.height >= 450 { + ScrollView { + infoSection + } + .frame(width: contentSize.width, height: contentSize.height) + } else { + HStack(alignment: .center, spacing: 0) { + infoSection + } + .frame(width: contentSize.width, height: contentSize.height) + .padding(0) + } + } + + var infoSection: some View { + VStack(alignment: .leading, spacing: 10) { + ForEach(section.fields) { field in + HStack(alignment: .center, spacing: 0) { + if let description = field.description { + Text(field.label) + .font(.body.bold()) + .frame(width: 80, alignment: .leading) + .fixedSize(horizontal: false, vertical: true) + Divider() + .padding(.horizontal) + Text(description) + .font(.body) + .fixedSize(horizontal: false, vertical: true) + } else { + Text(field.label) + .font(.body) + .frame(alignment: .leading) } } } - .padding() } - .frame(width: calculateIdealSize().width, height: calculateIdealSize().height) + .padding() } - func calculateIdealSize() -> CGSize { + // MARK: - Static Private Methods + + static private func calculateIdealSize(for section: InfoSection) -> CGSize { let maxWidth: CGFloat = 450 let maxHeight: CGFloat = 450 let dividerWidth: CGFloat = 30 - let fixedLabelWidth: CGFloat = 80 + let fixedLabelWidth: CGFloat = 78 let font = NSFont.preferredFont(forTextStyle: .body) - var totalHeight: CGFloat = 50 + var totalHeight: CGFloat = 22 var currentMaxWidth: CGFloat = 0 for field in section.fields { - let labelSize = field.label.size(withAttributes: [.font: font]) - let descriptionSize = field.description?.size(withAttributes: [.font: font]) ?? .zero - + let labelSize = (field.label as NSString).boundingRect(with: .init(width: field.description == nil ? maxWidth : fixedLabelWidth, height: 0), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [.font: font]).size + let descriptionSize = (field.description as? NSString)?.boundingRect(with: .init(width: 340, height: 0), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [.font: font]).size ?? .zero + let fieldWidth: CGFloat let fieldHeight: CGFloat if field.description != nil { - fieldWidth = fixedLabelWidth + dividerWidth + descriptionSize.width - fieldHeight = max(labelSize.height, descriptionSize.height) + fieldWidth = fixedLabelWidth + dividerWidth + descriptionSize.width + 50 + let labelLines = ceil(labelSize.width / fixedLabelWidth) + let labelHeight = labelLines > 1 ? labelLines * (labelSize.height+6) : labelSize.height + fieldHeight = max(labelHeight, descriptionSize.height) + 10 } else { fieldWidth = labelSize.width+50 - fieldHeight = labelSize.height+2.5 + fieldHeight = labelSize.height+10 } if fieldWidth > maxWidth { if field.description != nil { - let adjustedDescriptionWidth = maxWidth - fixedLabelWidth - dividerWidth - let descriptionHeight = ceil(descriptionSize.width / adjustedDescriptionWidth) * descriptionSize.height - totalHeight += max(labelSize.height, descriptionHeight) + let adjustedDescriptionWidth = maxWidth - fixedLabelWidth - dividerWidth - 50 + let descriptionLines = ceil(descriptionSize.width / adjustedDescriptionWidth) + let descriptionHeight = descriptionLines * descriptionSize.height + let labelLines = ceil(labelSize.width / fixedLabelWidth) + let labelHeight = labelLines * labelSize.height + totalHeight += max(labelHeight, descriptionHeight) currentMaxWidth = maxWidth } else { let adjustedLabelWidth = maxWidth - let labelHeight = ceil(labelSize.width / adjustedLabelWidth) * labelSize.height + let labelHeight = (ceil(fieldWidth / adjustedLabelWidth) * (labelSize.height+4)) + 10 totalHeight += labelHeight currentMaxWidth = maxWidth } @@ -105,11 +134,60 @@ struct InfoSectionView: View { return CGSize(width: min(maxWidth, currentMaxWidth), height: min(totalHeight, maxHeight)) } } + struct InfoSectionView_Previews: PreviewProvider { static var previews: some View { - InfoSectionView(section: InfoSection(fields: [InfoField(label: "First", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First"), - InfoField(label: "Second", description: "Second Second Second Second"), - InfoField(label: "Third", description: "Third"), - InfoField(label: "Fourth", description: "Fourth Fourth Fourth")])) + InfoSectionView(section: sectionnineth) } } + +let sectionone = InfoSection(fields: [InfoField(label: "First", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First"), + InfoField(label: "Second", description: "Second Second Second Second"), + InfoField(label: "Third", description: "Third"), + InfoField(label: "Fourth", description: "Fourth Fourth Fourth")]) + +let sectiontwo = InfoSection(fields: [InfoField(label: "First label"), + InfoField(label: "Second label"), + InfoField(label: "Third label"), + InfoField(label: "Fourth label")]) + +let sectionthree = InfoSection(fields: [InfoField(label: "First label"), + InfoField(label: "Second label")]) + +let sectionfour = InfoSection(fields: [InfoField(label: "First label First label First lab\n First label First label First label First label\nFirst label First label First label First label\nFirst label First label First label First label")]) + +let sectionfifth = InfoSection(fields: [InfoField(label: "First label"), + InfoField(label: "Second label"), + InfoField(label: "Third label"), + InfoField(label: "Fourth label"), + InfoField(label: "First label"), + InfoField(label: "Second label"), + InfoField(label: "Third label"), + InfoField(label: "Fourth label"), + InfoField(label: "First label"), + InfoField(label: "Second label"), + InfoField(label: "Third label"), + InfoField(label: "Fourth label")]) + +let sectionsixth = InfoSection(fields: [InfoField(label: "First First FirstFirst First", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First"), + InfoField(label: "Second First First First First First First", description: "Second Second Second Second"), + InfoField(label: "Third", description: "Third"), + InfoField(label: "Fourth", description: "Fourth Fourth Fourth")]) + +let sectionseventh = InfoSection(fields: [InfoField(label: "First First FirstFirst First", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First"), + InfoField(label: "Second First First First First First First", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First Second Second Second"), + InfoField(label: "Third", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First"), + InfoField(label: "Fourth", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First Fourth Fourth"), + InfoField(label: "Fourth", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First Fourth Fourth"), + InfoField(label: "Fourth", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First Fourth Fourth"), + InfoField(label: "Fourth", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First Fourth Fourth"), + InfoField(label: "Fourth", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First Fourth Fourth"), + InfoField(label: "Fourth", description: "First First First FirstFirst First First First First First First FirstvFirstFirstFirstFirstFirst FirstFirstFirst First First Fourth Fourth")]) + +let sectioneight = InfoSection(fields: [InfoField(label: "First label only only only", description: "First description only"), + InfoField(label: "Second label only only", description: "Second description only"), + InfoField(label: "Third label only only only", description: "Third description only")]) + +let sectionnineth = InfoSection(fields: [InfoField(label: "First label only", description: "First description only"), + InfoField(label: "Second label only", description: "Second description only"), + InfoField(label: "Third label only", description: "Third description only")])