My app is basically providing three option for selection to the user.
1: I am using result-view and cell-card. when i was using for each, i was able to click on the card and trigger an intent which is showing user the further details in the form of compound-card. Now, for user to select the option by saying first, second OR third, i need to use navigation-support and for that I need to use list-of in the result-view. After using list-of, I am unable to trigger the intent on-click. How to achieve that?
2: How to trigger that intent, if user is saying first, second or third. Right now, if user is choosing by saying first, second and third, it is popping out the said cell-card excluding other two. How to achieve that?
My result-view is:
result-view {
match: ArtistChoiceResult (artistchoice) {
from-output: ArtistChoice
}
message {template("Here is the upcoming event")}
list-of (artistchoice) {
navigation-mode {
read-many {
page-size(3)
underflow-statement (This is the first set)
item-selection-question (Which one would you like?)
overflow-statement (That's all I have)
}
}
where-each (one) {
layout-match (one) {
mode (Summary)
}
}
}
layout-match is like this
layout {
match: ArtistChoiceResult (singleArtist)
mode(Summary)
content{
section{
content{
cell-card {
slot1 {
image {
url ("#{value(singleArtist.multiple_image)}")
shape (Square)
}
}
slot2 {
content {
order (PrimarySecondary)
primary ("#{value(singleArtist.multiple_name)}")
secondary ("#{value(singleArtist.multiple_cat)}")
}
}
on-click {
intent {
goal: ArtistChoice
value-set:MultipleID{$expr(singleArtist.multiple_id)}
}
}
}
}
}
}
}
Navigation support file is
navigation-support {
match: ArtistChoiceResult (this)
ordinal-selection-patterns {
pattern ("(first)[v:viv.core.OrdinalSelector]")
pattern ("(first)[v:viv.core.OrdinalSelector] one")
pattern ("that (first)[v:viv.core.OrdinalSelector] one")
pattern ("yes (first)[v:viv.core.OrdinalSelector]")
pattern ("yes (first)[v:viv.core.OrdinalSelector] one")
pattern ("yes that (first)[v:viv.core.OrdinalSelector] one")
pattern ("result number (one)[v:viv.core.CardinalSelector:1]")
pattern ("the (first)[v:viv.core.CardinalSelector:1]")
pattern ("select (first)[v:viv.core.OrdinalSelector] one")
pattern ("select (first)[v:viv.core.OrdinalSelector]")
}
}
A couple of issues with your code
you have created an intent in a Summary layout. The documentation says,
https://bixbydevelopers.com/dev/docs/reference/type/layout-macro-def.content.cell-card
If you have this card to list results with list-of, then clicking the
card opens the selected item in Details mode and the defined intent is not passed
If you try to use layout-match inside where-each the IDE will show a WARN_DEPRECATED error. While this might not throw compile errors now, it is advisable to use layout-macro
Suggestions to try:
Use layout-macro to define your Layouts (both Summary and Details)
Add the intent in the Details layout
Related
I have some result views that use "has-details" which is now deprecated.
e.g.
render {
if (size(this) > 1) {
list-of (this) {
default-sort-order {
sorting(this.name)
}
has-details (true)
where-each (item) {
layout-macro (altbrains-compound-card) {
param (altbrainsdata) {
expression (item)
}
}
}
}
https://bixbydevelopers.com/dev/docs/dev-guide/release-notes/deprecations.6812
DEPRECATED: has-details is deprecated. Consider using on-click.view-for in a list card components instead. [deprecation 6812]
What does this mean? Can someone provide an example?
The Movie Agent Sample Capsule in the Bixby Developers Github repo is an excellent example for this behavior.
The relevant files are:
Movie_Result.view.bxb
Movie_Summary.layout.bxb
Movie_Details.layout.bxb
Here's how it works:
User asks for something that results in multiple Movies
Movie_Result view displays a bunch of movies using the Movie_Summary layout macro for each Movie
User taps one Movie which triggers the on-click containing view-for (movie)
This reloads the Movie_Result view again since its match requirement is met and triggers the Movie_Details layout since there is only 1 Movie to display.
I have used hands-free list-of navigation in my capsule where I select a single item from multiple items to get the detailed information using voice command ("select one, choose second, etc").
But If I have a single item only, I am unable to give a voice command to go to another page. (hands-free list-of navigation not working when we have a single item).
So, how can I go to another page when I have a single item only, using voice command. (hands-free navigation)
Please help me with this.
For a single item case, should be checked first and probably not enter list-navigation at all. The logic for render in view is recommended as following:
if (size(this)==1) {
// render content (maybe different between HEF and non-HEF, but no navigation needed)
}
else {
if ($handsFree) {
// do list navigation here
}
else {
// render non-HEF content
}
}
Please consider the following code as a sample, this view works for multiple item list and single item. For HEF with multiple items, the flow is "do you want one of these" --> "yes" --> "which person would you like" --> "first/second one" --> Bixby renders the content in detail-stuctA macro. For HEF with single item, it directly renders detail-stuctA macro and skip all the navigation part.
It is true that if skip the (size(this)==1) check would result stuck in list-navigation forever, but that is understandable, because each time Bixby try to render, it fits the condition of list-navigation and take the list-navigation route.
result-view {
match: StructA(this)
message: template ("In result view")
render {
if (size(this)==1) {
layout-macro (detail-structA) {
param (person) {expression (this)}
}
}
else {
if ($handsFree) {
list-of (this) {
navigation-mode {
read-many {
page-size (6)
list-summary("In hands free")
page-content {
underflow-statement (This is the first page.)
page-selection-question (Do you want one of these?)
item-selection-question (Which person would you like?)
overflow-statement (Those are all the persons that meet your search.)
overflow-question (What would you like to do?)
}
}
}
where-each (item) {
layout-macro (summary-structA) {
param (person) {expression (item)}
}
}
}
}
else {
list-of (this) {
where-each (item) {
layout-macro (summary-structA) {
param (person) {expression (item)}
}
}
}
}
}
}
}
If the above does not answer your question, please submit a ticket using Bixby IDE --> Help --> Contact Support with a copy of sample capsule to demo the issue.
I've tried implementing an input-view with navigation-mode so that the user can verbally select an option. The goal is to have my capsule completely usable without physical interaction.
The issue is that I tried to follow the example from the Developer Center, but it doesn't seem to work properly. https://bixbydevelopers.com/dev/docs/dev-guide/developers/enhancing-UX.list-navigation
input-view {
match: SpaceResort (result)
message ("Which space resort would you like?")
render {
if (size(result) > 1) {
selection-of (result) {
navigation-mode {
read-one {
list-summary ("I found #{size(result)} resorts.")
page-content {
underflow-statement (This is the first resort.)
item-selection-question (Do you want to book this resort?)
overflow-statement (Those are all the resorts that meet your search.)
overflow-question (What would you like to do?)
}
}
}
has-details (true)
select-button-text ("Book")
where-each (item) {
layout-macro (space-resort-summary) {
param (spaceResort) {
expression (item)
}
}
}
}
}
}
}
On my capsule, it would repeat the 'item-selection-question', 'list-summary', or the message template twice, and it will not read out loud the list of items.
The online DOC example is not very clear.
You need to add child-key spoken-summary in where-each (item). Please check more here
And in IDE testing, you need enable the "hands free" mode button.
Currently on-device testing this feature is not enabled, yet.
Again, the repeat twice message is a bug, and will be fixed soon.
I would like to collect an address input for an action "evaluate". Ideally the behavior would be something like this:
1) Evaluate is initiated
2) a default address is pulled from user profile,
user is asked if they would like to use this address
3) if no default address or user does not want to use it,
prompt user for an address
4) Evaluate action runs with either default address or custom input address
What I am thinking of doing is adding 2 constructor actions that could potentially return a geo.Address object, ReturnSelfAddress and GetCustomAddress. ReturnSelfAddress will collect an address from the self library capsule and GetCustomAddress will prompt the user to enter an address as a geo.UnstructuredAddress and convert that into a regular geo.Address.
The input to the Evaluate action is this:
input (address) {
type (geo.Address)
min (Required)
max (One)
default-init {
intent {
goal: ReturnSelfAddress
}
}
}
Then I would have a confirmation view that would confirm ReturnSelfAddress to let the user select that if desired. If ReturnSelfAddress fails, then Evaluate will still look for a geo.Address input. I would have an input-view that would match the geo.Address concept and prompt the user to input a geo.UnstructuredAddress. Something like this (not sure if this is 100% correct):
input-view {
match: geo.Address(this)
message ("What is your street address?")
render{
form {
elements {
text-input {
id (address)
label("Address")
required (true)
type (geo.UnstructuredAddress)
}
}
on-submit {
goal: GetCustomAddress
value: viv.core.FormElement(address)
}
}
}
}
Alternatively, if the user rejects the default, then I will have an on-abort goal of GetCustomAddress that would prompt the user:
on-abort {
intent {
goal: GetCustomAddress
}
}
This seems to be very involved, and I am questioning if there is a feature that i might be missing that will help me get the desired behavior. So i guess i have 2 questions:
1) Before i go too deep down this rabbit hole, will this idea work?
2) Is there a better way to get the desired behavior of "try for default and if none or user rejects, prompt for input"?
You can try the confirmation view, but here is an easier way you might find useful.
Define the input in action model with default-init and prompt-behavior (AlwaysElicitation)
input (email) {
type (TypeTextEmail)
min (Required) max (One)
default-init {
intent {
goal: FetchEmailFromName
value: $expr(name)
}
}
prompt-behavior (AlwaysElicitation)
}
Define input view to overwrite the default if user want to
input-view {
match: TypeTextEmail(this)
render {
form {
elements {
text-input {
id (this)
type (TypeTextEmail)
label ("Email:")
max-length (50)
value ("#{value(this)}")
}
}
on-submit {
goal: TypeTextEmail
value: viv.core.FormElement(this)
}
}
}
}
You can download and try the training example in example.inputview
For confirmation view, please refer the example.shirt on Github
I am trying to open google maps using the on-click key from a compound card, but I don't know what to include in the payload-URI key for app-launch. The documentation uses the example which is commented out, but I do not know what to fill in for the application(google-maps).
I am getting two errors both being Unknown key message/app-launch.
This is the code we are trying to use, so that when a compound card is clicked, it opens google maps with app-launch.
// PersonSelectionView.view.bxb
input-view {
match: Spot (this)
// optional selection dialog to overwrite any other default dialog
message (Pick a spot)
render {
// used to iterate over the list of candidates
selection-of (this) {
navigation-mode {
read-none {
list-summary ("There are #{size(this)} #{value(categories)} spots near you")
item-selection-question (Which one would you like?)
}
}
where-each (one) {
// you can use conditional logic to control how candidates are displayed,
// using either a standard layout with a match pattern, or a layout macro
compound-card {
content {
map-card {
title-area {
slot1 {
text {
value("#{value (one.spotName)}")
}
}
slot3 {
single-line {
text {
value("#{value (one.distance)} Miles away")
}
}
}
}
aspect-ratio (1:1)
markers {
marker {
geo ("Location.point")
icon {
template (/images/icons/red-marker.png)
}
width (15)
height (20)
anchor-x (5)
anchor-y (15)
rotation (0)
}
}
}
paragraph {
value {
template ("#{raw(description)}")
}
style (Detail_L)
}
}
on-click {
message ("TESTING THIS MESSAGE")
app-launch {
//payload-uri ("bixby://com.android.systemui/DummySystem/punchOut")
}
}
}
}
}
}
}
An "Unknown Key" error means that the key you are trying to define is not one of the valid child keys of the key you are currently in. The reference section of the Bixby Developer Documentation provides each key with its valid child keys.
Both app-launch and message are not child keys of on-click.
app-launch cannot be defined within an on-click. It must be defined in its own result-view.
message can be defined in multiple keys but not on-click
Your on-click would need to redirect to a separate result-view which would contain the app-launch key with the correct payload-uri defined.
You would need the following to implement the behavior you described:
An Action (and backing Action Javascript) to return the URI
A Concept to hold the URI returned by the Action
A result-view with a match that matches the Concept
Example Action:
action (LaunchDefinedUri) {
description (Launches the defined uri)
type (Commit)
collect {
input (launchUri) {
type (LaunchUri)
min (Required) max (One)
}
}
output (LaunchUri)
}
Example Action Javascript:
module.exports = {
function: LaunchDefinedUri
}
function LaunchDefinedUri(launchUri) {
return launchUri
}
Example Concept:
text (LaunchUri) {
description (Uri to be launched)
}
Example Result View:
result-view {
match: LaunchUri(this)
app-launch {
payload-uri("#{value(this)}")
}
render {
nothing
}
}
As for Google Maps API in particular, the Google Maps documentation seems to provide information on how to define the correct URIs for your specific purpose and behavior.
Please look into this official library provided by the Bixby team, which provides punch-out to Google Maps.
https://bixbydevelopers.com/dev/docs/dev-guide/developers/library.navigation