3 min read
Common customisations
Add SlotsContent to a domain model
If you want to add Dynamic content to a domain model and start receiving content through the API, you need to:
- Add SlotsContent model to your domain model.
- Add
List<NetworkSlotResponse>?
to your network model. - Use NetworkToDomainSlotsContentMapper to map between network and domain models.
- Call GetDynamicContentRequest to get all DynamicContentRequest.
- Use MapDynamicContentHeaders to map all
DynamicContentRequest
to headers. - Add the mapped dynamic content requests headers to your API request.
Add a new Slot to a screen
If you want to add a new Slot to a screen where the domain model already contains SlotsContents
, you need to use different components depending if you will add it to Compose, a View or a RecyclerView.
Compose
- Add
UiSlotsContent
to your UI state model mapping it fromSlotsContent
using DomainToUiSlotsContentMapper. - On your composable, get the
UiSlotComponent
from theUiSlotsContent.components
Map using the slot id for the slot to render. - Use SlotComponentComposable to display your
UiSlotComponent
.
View
- Expose
UiSlotsContent
on your ViewModel mapping it fromSlotsContent
using DomainToUiSlotsContentMapper. - Add PoqSlotComponentView to your view hierarchy.
- Use the binding adapter to send the appropiate
UiSlotComponent
:<com.poqstudio.platform.content.dynamiccontent.ui.PoqSlotComponentViewandroid:layout_width="match_parent"android:layout_height="wrap_content"app:slot='@{"top"}' // Use your SlotIdapp:slotsContent="@{viewModel.slots}" />
RecyclerView
- Add
UiSlotComponent
to your the RecyclerView UI model mapping it fromSlotsContent.component
using DomainToUiSlotComponentMapper using the appropriate slot id for your slot. - Use SlotComponentViewHolderFactory to create a BaseSlotComponentViewHolder.
- Call
BaseSlotComponentViewHolder.onBind
passing the appropriateUiSlotComponent
:override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {return when (viewType) {TYPE_SLOT_COMPONENT -> slotComponentViewHolderFactory.create(parent)...}}override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {when (getItemViewType(position)) {TYPE_SLOT_COMPONENT -> (viewHolder as BaseSlotComponentViewHolder).onBind((getItem(position) as YourUiModel.SlotComponent).component,)...}}
Create a new SlotComponent
Dynamic content supports custom SlotComponents
. To create a new SlotComponent
you need to:
- Define the network model for your new SlotComponent.
- Define your domain model that implements
SlotComponentCustomCustomData
which your new Composable will receive. - Define your network to domain mapper that implements NetworkToDomainSlotComponentCustomMapper.
content: Any
can be safely cast to your network model. - To support
DynamicAction.UpdateComponent
, you need to:- Define your update model that implements
SlotComponentCustomUpdateCustomData
which usually is a copy of your domain model with all fields nullable. - Define your update to domain mapper that implements SlotComponentCustomUpdateToCustomDataMapper where you create a new
SlotComponentCustomCustomData
updating the existing one with the new field received onSlotComponentCustomUpdateCustomData
- Define your update model that implements
- Create your new Composable component that receives a Modifier and the UiSlotComponent.
- Create an object of CustomSlotComponentRegister.Default in your
Application.onCreate
:CustomSlotComponentRegister.Default(slotComponentType = "your slot component type identifier",networkToDomainMapper = inject<MyNetworkToDomainlotComponentCustomMapper>(),networkModelClass = MyNetworkSlotComponent::class.java,updateMapper = inject<MySlotComponentCustomUpdateToCustomDataMapper>(),composable = { modifier, slotComponent -> MySlotComponent(modifier, slotComponent.customData as MyDomainModel) },).register()
Custom SlotComponent with validation
If your new SlotComponent requires validation rules (such as a mandatory text field), your domain model needs to also implement UiValidationComponent
Create a new SlotComponent Container
Dynamic content supports custom SlotComponents Container
, a specialized component that shows other components (like a column or a row). To create a new SlotComponent.Container
, the steps are the same as create a default SlotComponent with these differences:
- Your network to domain mapper needs to implement NetworkToDomainSlotComponentCustomContainerMapper
- Create an object of CustomSlotComponentRegister.Container in your
Application.onCreate
:CustomSlotComponentRegister.Container(slotComponentType = "your slot component type identifier",networkToDomainMapper = inject<MyNetworkToDomainSlotComponentCustomContainerMapper>(),networkModelClass = MyNetworkSlotComponent::class.java,updateMapper = inject<MySlotComponentCustomUpdateToCustomDataMapper>(),composable = { modifier, slotComponent -> MySlotComponent(modifier, slotComponent.customData as MyDomainModel) },).register()
Create a new Modifier
Dynamic content supports the creation of custom modifiers. To create a new Modifier, you need to:
- Define your network model that implements
NetworkSlotComponentModifiersCustomData
defining all your new Modifiers. - Define your domain model that implements
SlotComponentModifierCustomCustomData
defining all your new Modifiers. - Define your network to domain mapper that implements NetworkToDomainSlotComponentCustomDataMapper and provide your implementation via Koin.
- Define your domain to UI mapper that implements DomainToUiModifierCustomMapper returning all your new modifiers as a single Compose modifier. Provide your mapper implementation via Koin.
How to add a new headers to Dynamic content requests
Dynamic content supports adding new headers to all requests. To add a new headers, you need to:
- Define your domain modile that implements
DynamicContentRequestCustomData
defining your extra header data. - Decorate
GetDynamicContentRequest
to include your new data intoDynamicContentRequest
. - Decorate
MapDynamicContentHeaders
to map your new header and merge it with result from the PoqSDK implementation.
How to add a new custom conditions to the existing header
Dynamic content supports conditions to personalize the content. To add custom conditions, you need to include them into DynamicContentRequest.customConditions
, the PoqSDK takes care of the rest. You can include your custom conditions decorating GetDynamicContentRequest
if you want to include them to all Dynamic content requests.
How to add a new Dynamic content provider
Dynamic content supports the personalisation of the content via API headers defined with DynamicContentUser
. If you need to add a new Dynamic content provider, you need to:
- Define your user model that implements DynamicContentUser
- Define your user initializer use case that complies with DynamicContentUserInitializer
- Define your get user use case that complies with DynamicContentUserGetter
- Define the mapper between your user and API headers that complies with DynamicUserHeadersMapper
- Call InitDynamicContentUsers.addInitializer, GetDynamicContentUsers.addGetter and MapDynamicUsersHeaders.addMapper in your
Application.onCreate
with your new classes.
Create a new Dynamic action
Dynamic content supports custom DynamicAction
. To create a new DynamicAction
you need to:
- Define the network model for your new DynamicAction.
- Define your domain model that implements
DynamicActionCustomCustomData
which your new action will receive. - Define your network to domain mapper that implements NetworkToDomainDynamicActionCustomMapper.
content: Any
can be safely cast to your network model. - You can create these custom actions:
Default
: a generic DynamicAction. You need to implementdefaultAction
function.Navigation
: a DynamicAction to navigate the user. You need to implementnavigate
function with your navigation logic.Suspend
: a DynamicAction to long operation which requires show a loading to the user. You need to implementsuspendAction
function
- Create an object of CustomDynamicActionRegister in your
Application.onCreate
:CustomSlotComponentRegister.{Type}(action = "your new action type identifier",networkToDomainMapper = inject<MyNetworkToDomainDynamicActionCustomMapper>(),networkModelClass = MyNetworkDynamicActionClass::class.java,action = { ... },).register()
How to support Dynamic actions on a new screen
If you are adding slots to a new screen and you want to support dynamic actions on that screen, you need to:
- Implement
DynamicActionHost
on your ViewModel where:dynamicPageId: String?
: unique id for your screendynamicContext: MutableDynamicContext
: usually an empty mutable map.setIsLoading(isLoading: Boolean)
: add logic to hide/show a loading statesetError(poqError: PoqError)
: add logic to show an error statenavigate(action: DynamicAction.Navigation)
: add logic to Navigate, you can use DynamicActionNavigatoronDynamicAction(actions: List<DynamicAction>)
: add logic to handle dynamic actions using DynamicActionListHandler
- Send your instance of your
DynamicActionHost
to theUiSlotComponents
, usually using DomainToUiSlotComponentMapper