Closed philippzagar closed 8 months ago
Hi @PSchmiedmayer,
here is the first draft of the consent export functionality PR. The overall export works reasonably well, see an example exported consent form. However, I'm a bit stuck about the integration in the overall Onboarding API. My ideal usage of the export functionality would be something like:
Export(size: .usLetter, destinationPath: ...) { render in
ConsentView(
...,
action: {
render()
onboardingNavigationPath.nextStep()
}
)
}
However, this is prohibited by a multitude of factors, such as the fact that all SwiftUI views are structs, the action
closure of the ConsentView
is escaping, all data is passed down to the "child" views of the ConsentView
(such as the OnboardingActionView
) directly in the initializer (including the closures) etc.
This constraints the current export design by quite a lot. I don't want to tear down too much of the existing structure of the Onboarding module without consulting you first.
The goal would be to have a simple usable API as explained above. At the moment it's implemented via a simple hardcoded Button in the ConsentView
(to demonstrate the functionality) and only for MD as HTML is a bit trickier to deal with (but not impossible). Also, I plan to give the user the option to easily store the consent form via the adjustments made in the OnboardingActionView
to enable horizontal button layouts.
Do you have any design suggestions that would make this functionality nicely integrated, configurable, and extensible for future consent data types? I'm quite stuck here at the moment...
Thank you for the progress in this PR @philippzagar!
I would suggest two things:
Standard
mechanisms here: https://swiftpackageindex.com/stanfordspezi/spezi/documentation/spezi/component#Component-Constraints. This would allow you to pass the finished PDF to the standard and a user can then decide where to put it (e.g. upload or store locally) and how that should be processed is then defined by the Standard
instance, a unique environment object that is a reference type. You can see how we use that mechanism over in Spezi Questionnaire: https://github.com/StanfordSpezi/SpeziQuestionnaireHope this solves your questions and unblocks you from the next steps. Let me know if you have any questions! 🚀
Merging #26 (75472f0) into main (13efb08) will increase coverage by
1.07%
. The diff coverage is81.09%
.
Hi @PSchmiedmayer,
thanks for the input! 🚀
Regarding 1:
Yeah, that probably makes sense, do a first working draft now and expand upon it later (including additions to SpeziViews
). As mentioned, the consent export (especially with different formats) isn't a trivial topic and could become quite complex.
Regarding 2:
Thanks for the input but I guess you misunderstood my issue a bit. I already use the Standard
as well as Constraints in order to store the resulting PDF and let the user decide what to do with the rendered document, that's not the issue here. The main issue is that I'm not sure how to trigger the rendering process when the user proceeds to the next onboarding view. As mentioned, the closure (primaryAction
) from the OnboardingActionView
used for moving to the next onboarding step is escaping and created in the initializer of the ConsentView
, meaning we don't have access to the respective ConsentView
instance from inside that closure (which includes all the necessary data points).
My current workaround is to use the .simultaneousGesture()
modifier on the action
subview in the ConsentView
in order to detect taps on the action buttons in the OnboardingActionView
but also the ConsentView
. This works, but it is kind of an ugly workaround. Furthermore, it doesn't enable the implementation of features like a personal "Share" button for users directly on the consent page (e.g., via the secondaryAction
of the OnboardingActionView
).
Any clues on how we could proceed here without tearing down too much of the existing onboarding infrastructure? (especially OnboardingActionView
). For now, it is definitely an option to just merge as is (as we are under time pressure), but I would definitely suggest a follow-up PR that expands and refines the export functionality.
@PSchmiedmayer Thanks for the great feedback! I incorporated it, please review the current state of the PR 🚀
As mentioned yesterday, a couple of warnings are still thrown when using the iOS Share Sheet functionality (from UIKit):
Only support loading options for CKShare and SWY types.
error fetching item for URL:file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/B8A80EF1-2820-46D9-8A4D-B653F5FE4AB7/data/Containers/Data/Application/E0B221BD-0A7C-41B4-9EFF-14AD2FBF5FDD/tmp/Signed%20Consent%20Form.pdf :
error fetching file provider domain for URL:file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/B8A80EF1-2820-46D9-8A4D-B653F5FE4AB7/data/Containers/Data/Application/E0B221BD-0A7C-41B4-9EFF-14AD2FBF5FDD/tmp/Signed%20Consent%20Form.pdf :
Collaboration: error loading metadata for documentURL:file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/B8A80EF1-2820-46D9-8A4D-B653F5FE4AB7/data/Containers/Data/Application/E0B221BD-0A7C-41B4-9EFF-14AD2FBF5FDD/tmp/Signed%20Consent%20Form.pdf error:Error Domain=NSFileProviderInternalErrorDomain Code=0 "No valid file provider found from URL file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/B8A80EF1-2820-46D9-8A4D-B653F5FE4AB7/data/Containers/Data/Application/E0B221BD-0A7C-41B4-9EFF-14AD2FBF5FDD/tmp/Signed%20Consent%20Form.pdf." UserInfo={NSLocalizedDescription=No valid file provider found from URL file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/B8A80EF1-2820-46D9-8A4D-B653F5FE4AB7/data/Containers/Data/Application/E0B221BD-0A7C-41B4-9EFF-14AD2FBF5FDD/tmp/Signed%20Consent%20Form.pdf.}
Error acquiring assertion: <Error Domain=RBSServiceErrorDomain Code=1 "(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)" UserInfo={NSLocalizedFailureReason=(originator doesn't have entitlement com.apple.runningboard.primitiveattribute AND originator doesn't have entitlement com.apple.runningboard.assertions.frontboard AND target is not running or doesn't have entitlement com.apple.runningboard.trustedtarget AND Target not hosted by originator)}>
Not sure if we can do smt about that, as it apparently has smt. to do with permissions set in the Info.plist file: https://stackoverflow.com/questions/76740143/sharesheet-fails-to-open-a-local-file Apparently (somehow related to this) it also may be (partly) a bug of iOS17: https://developer.apple.com/forums/thread/737721
Warnings under iOS16:
Only support loading options for CKShare and SWY types.
error fetching item for URL:file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/7F4D9524-B4DF-45C4-AB41-2A4BF0BBC85D/data/Containers/Data/Application/6604A4BA-C17B-45BE-9FAF-E9582788CCA3/tmp/Signed%20Consent%20Form.pdf : (null)
error fetching file provider domain for URL:file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/7F4D9524-B4DF-45C4-AB41-2A4BF0BBC85D/data/Containers/Data/Application/6604A4BA-C17B-45BE-9FAF-E9582788CCA3/tmp/Signed%20Consent%20Form.pdf : (null)
error loading metadata for documentURL:file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/7F4D9524-B4DF-45C4-AB41-2A4BF0BBC85D/data/Containers/Data/Application/6604A4BA-C17B-45BE-9FAF-E9582788CCA3/tmp/Signed%20Consent%20Form.pdf error:Error Domain=NSFileProviderInternalErrorDomain Code=0 "No valid file provider found from URL file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/7F4D9524-B4DF-45C4-AB41-2A4BF0BBC85D/data/Containers/Data/Application/6604A4BA-C17B-45BE-9FAF-E9582788CCA3/tmp/Signed%20Consent%20Form.pdf." UserInfo={NSLocalizedDescription=No valid file provider found from URL file:///Users/philippzagar/Library/Developer/CoreSimulator/Devices/7F4D9524-B4DF-45C4-AB41-2A4BF0BBC85D/data/Containers/Data/Application/6604A4BA-C17B-45BE-9FAF-E9582788CCA3/tmp/Signed%20Consent%20Form.pdf.}
Export Consent Forms (Markdown)
:recycle: Current situation & Problem
Until now, users could view and sign a consent document using the SpeziOnboarding package. However, the package did not offer any provision to save or export the signed consent document. In the medical domain, the consent form collection is especially important in order to serve as legal cover. See #7.
:gear: Release Notes
ConsentView
has been renamed toOnboardingConsentView
and includes breaking changes to its public API. TheOnboardingConsentView
now provides an export functionality of the signed form in PDF format to the SpeziStandard
and to an iOS share sheet. TheStandard
needs to conform toOnboardingConstraint
to handle the exported form.ConsentDocument
has been introduced, giving developers access to the underlying signature and export functionality of theOnboardingConsentView
enabling more customizations by the developer. The functionality of theConsentDocument
can be observed and controlled via aConsentViewState
passed to the view via a SwiftUIBinding
.:books: Documentation
Documentation is provided via DocC in-line comments. Additional DocC documentation documents are adjusted and refer to the new export functionality.
:white_check_mark: Testing
UI Test cases written and adapted.
:pencil: Code of Conduct & Contributing Guidelines
By submitting creating this pull request, you agree to follow our Code of Conduct and Contributing Guidelines: