Carousel wants to bring all non zero indexed child to pinned focus offset

:warning: Before you continue


Before submitting a bug report, please review our troubleshooting documentation at Troubleshoot Issues | Vega Troubleshooting

If you still want to file a bug report, please make sure to fill in all the details below and provide the necessary information.

NOTE: PLEASE ONLY REPORT A SINGLE BUG USING THIS TEMPLATE.
If you’re experiencing multiple issues, please file a separate report for each.


:backhand_index_pointing_right: Bug Description


1. Summary

On initial mount,Carousel tries to bring its child to pinned focus offset even if that won’t be its normal position during remote scroll

App Name:
App Link on Amazon Appstore (found through Developer Console → Actions column in App List → View on Amazon.com):

Bug Severity
Select one that applies

  • Impacts operation of app
  • Blocks current development
  • Improvement suggestion
  • Issue with documentation (If selected, please share the doc link and describe the issue)
  • Other

2. Steps to Reproduce

  1. put initialStartIndex to any child at index>0 and whose normal position if user was scrolling from top of list to that child would not be at that pinned focus offset.
  2. The child at initial start index request focus on initial mount.
  3. Also, for comparison purposes, put initial start index to 0, ask child at index 0 to request focus, and then see the normal scrolling position when user focuses that previous start index using remote.

3. Observed Behavior

Explain what actually happened, noting any discrepancies or malfunctions.

1)if the normal scroll position of DPad scroll is not at pinned focus offset, and child is near to start of the list, the list is pushed downwards on initial mount, if its closer to end of the list, it is pushed upwards

2)If

4. Expected Behavior

Describe what you expected the SDK to do under normal operation.

on initial mount, the child should only be bought to pinned focus offset if during scrolling and focusing done by remote , that would be its normal position.

4.a Possible Root Cause & Temporary Workaround

Fill out anything you have tried. If you don’t know, N/A is acceptable

N/A

5. Logs or crash report

(Please make sure to provide relevant logs as attachment)

For crash issues, please refer this guide for faster troubleshooting: Detect Where the App Crash Originates | Design and Develop Vega Apps

  • App/Device Logs

  • Crash Logs

  • Crash Report

  • For issues with Vega Studio Extension, please share log files from below folders:
    For v0.22+:

    ~/.vscode/extensions/amazon.vega-extension-<version>/ExtensionLogs
    ~/.vscode/extensions/amazon.vega-ui-extension-<version>/ExtensionLogs
    

    For v0.21 and earlier:

     ~/.vscode/extensions/amazon.kepler-extension-<version>/ExtensionLogs
     ~/.vscode/extensions/amazon.kepler-ui-extension-<version>/ExtensionLogs
    

6. Environment

Please fill out the fields related to your bug below:

  • SDK Version: Run vega --version (v0.22+) or kepler --version (v0.21 and earlier) and paste output

  • App State: [Foreground]

  • OS Information: Please ssh into the device via vega exec vda shell (or kepler exec vda shell for v0.21 and earlier) and copy the output from cat /etc/os-release into the answer section below. Note, if you don’t have a simulator running or device attached, the command will respond with vda: no devices/emulators found

    <!-- Answer here if applicable --> 
    

7. Example Code Snippet / Screenshots / Screengrabs

Include any relevant code or component setup in React Native that can help reproduce the bug.

import { Carousel, type ItemInfo } from '@amazon-devices/kepler-ui-components'
import { useEffect, useRef, useState } from 'react'
import { Dimensions, FocusManager, Pressable, StyleSheet, Text, View, findNodeHandle, type View as ViewType } from 'react-native'

const BASE_HEIGHT = 1080

function scalePixels(size: number): number {
  return Math.round((size * Dimensions.get('window').height) / BASE_HEIGHT)
}

const ITEMS = [
  'random-text-one',
  'random-text-2',
  'random-text-3',
  'random-text-4',
  'random-text-5',
  'random-text-6',
  'random-text-7',
  'random-text-8',
  'random-text-9',
  'random-text-10',
]

const CARD_WIDTH = scalePixels(200)

const CardView = () => null

const itemInfo: ItemInfo[] = [
  {
    view: CardView,
    dimension: { width: CARD_WIDTH, height: CARD_WIDTH },
  },
]

const getItemForIndex = () => CardView

type CardProps = {
  item: string
  index: number
  itemRef: React.RefObject<ViewType>
  focusRequest: number | undefined
  setFocusRequest: (index: number | undefined) => void
}

const Card = ({ item, itemRef, index, focusRequest, setFocusRequest }: CardProps) => {
  const [isFocused, setFocused] = useState(false)

  const styles = useStyles(isFocused)

  useEffect(() => {
    if (focusRequest === index) {
      const handle = findNodeHandle(itemRef.current)
      if (handle) FocusManager.focus(handle)
      setFocusRequest(undefined)
    }
  }, [focusRequest, index, itemRef, setFocusRequest])

  return (
    <Pressable
      style={styles.pressable}
      ref={itemRef}
      onFocus={() => setFocused(true)}
      onBlur={() => setFocused(false)}
    >
      <View>
      <Text style={styles.text}>{item}</Text>
      </View>
    </Pressable>
  )
}

export default function SampleCode() {
  const itemRefs = useRef<React.RefObject<ViewType>[]>(
    ITEMS.map(() => ({ current: null })),
  )

  const [focusRequest, setFocusRequest] = useState<number | undefined>(1)

  return (
    <View style={mainStyles.screen}>
      <Carousel
        orientation="vertical"
        data={ITEMS}
        firstItemOffset={20}
        itemDimensions={itemInfo}
        getItemForIndex={getItemForIndex}
        keyProvider={(item) => item}
        initialStartIndex={1}
        numOffsetItems={2}
        maxToRenderPerBatch={6}
        trapFocusOnAxis
        pinnedFocusOffset='50%'
        focusIndicatorType="pinned"
        containerStyle={mainStyles.carousel}
        renderItem={({ item, index }) => (
          <Card
            item={item}
            index={index}
            itemRef={itemRefs.current[index]}
            focusRequest={focusRequest}
            setFocusRequest={setFocusRequest}
          />
        )}
      />
    </View>
  )
}

const mainStyles = StyleSheet.create({
  screen: {
    width: '100%',
    height:'100%'
  },
  carousel: {
    width: CARD_WIDTH,
    height: scalePixels(1080),
  }
})

const useStyles = (isFocused: boolean) =>
  StyleSheet.create({
    pressable: {
    backgroundColor: isFocused ? '#008000': '#FF0000',
    width:CARD_WIDTH,
    height:CARD_WIDTH,
  },
    text: {
    color: '#ffffff',
    fontSize: 32,
  },
  })


:backhand_index_pointing_right: Playback Issues


If this is a playback issue, please provide your content URL, any pre-conditions (like geo-location), and let us know if it’s x86 or arm7.


<!-- Describe your playback issue if applicable -->

Please share the following details in addition:_

  • Player SDK: [Bitmovin, Shaka, ...]
  • Player SDK Version: [e.g. 1.23]
    • Audio Codecs: [AAC, ...]
    • Video Codecs: [h.264, mp4]
    • Manifest Types: [m3u8, dash, etc ..]

Q: If applicable, please provide your media/content url
If this is created dynamically, tokenized, etc please provide a way for us to access it

[N/A or Content / Media Url for testing]

Q: Are there any special headers required to reproduce the issue you are facing?

[N/A or Insert Headers]

Additionally please provide the following if possible
Provide Screenshots / Screengrabs / Logs. Please include as much information as you can that will help debug.

<!-- Answer here if applicable --> 

:backhand_index_pointing_right: Additional Context


Any Additional Context you would like to provide?
Add any other relevant information, such as recent updates to the SDK, dependencies, or device OS that may affect the bug.


Hi @Rishabh_Ritweek,

Thank you for the detailed bug report on the Carousel pinned focus offset issue.

Our team is investigating this. To help with the analysis, could you please share the relevant app/device logs from your environment? You can find them at:

  • v0.22+: ~/.vscode/extensions/amazon.vega-extension-<version>/ExtensionLogs
  • v0.21 and earlier: ~/.vscode/extensions/amazon.kepler-extension-<version>/ExtensionLogs

We’ll provide an update as soon as we have more information.

Thanks for helping us improve the Vega platform.

Warm regards,
Aishwarya

my kepler version is 0.20.3154 but i cannot find any such directory

Hi @Rishabh_Ritweek,

Thanks for the follow-up. You can collect them using the Vega CLI:

kepler device copy-logs

For more details on collecting logs, please see:

Please share the collected logs and we’ll continue investigating.

Warm regards,
Aishwarya

Hello I believe logs are no longer needed now.

i want to emphasize that snapping children to pinned focus offset on initial mount and initial focus is desired but not always.It should only happen if remote initiated scroll, from top to bottom or bottom to top would bring that child to the pinned focus offset. As for given code snippet, For children at index 1, this should not happen. for index 2, it should happen.Again specific indicies where it should not happen can depend on height of children, length of array as well but you will find them more often at/near begining and start of the list.