Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

navigating to the next close sibling instead of the target when using manual navigation #146

Open
aymaneallaoui opened this issue Oct 12, 2024 · 0 comments

Comments

@aymaneallaoui
Copy link

bug :

when i try to manually set the navigation it it skip to next close sibling instead of the navigating to the target

video demo

2024-10-12.18-24-59.mp4

code to reproduce

import { FocusContext, setFocus, useFocusable } from "@noriginmedia/norigin-spatial-navigation";

import EpisodeCard from "./ep-card";
import StarRating from "../global/star-rating"
import dataShape from "./dataShape.json"
import { useCallback } from "react";
import { useEffect } from "react";
import { useRef } from "react";

/* eslint-disable no-unused-vars */



function InfoSeries() {
    const { ref, focusKey } = useFocusable()
    const { ref: movieRef, focused } = useFocusable({
        focusKey: "movie-info",
        onFocus: (layout, props) => {

            handleScroll(movieRef);

        },
        onArrowPress: (direction) => {
            if (['down', 'right', 'left', 'up'].includes(direction)) {
                setFocus("back-series")
            }

            return true
        }
    })

    const { ref: backSeriesRef, focused: focusBackSeries } = useFocusable({
        focusKey: "back-series",
        onFocus: (layout, props) => {

            handleScroll(backSeriesRef);

        },
        onArrowPress: (direction) => {
            switch (direction) {
                case 'down':
                    setFocus(`ep-${dataShape.episodes["1"][0].id}`)
                    break;
                case 'up':
                    setFocus(`movie-info`)
                    break
                case 'right':
                    setFocus('back-categories')
                    break
                case 'left':
                    setFocus('back-main')
                    break
            }
        }
    })

    const { ref: backCategoriesRef, focused: focusBackCategories } = useFocusable({
        focusKey: "back-categories",
        onFocus: (layout, props) => {

            handleScroll(backCategoriesRef);

        },
        onArrowPress: (direction) => {

            switch (direction) {
                case 'down':
                    setFocus(`ep-${dataShape.episodes["1"][0].id}`)
                    break;
                case 'up':
                    setFocus(`movie-info`)
                    break
                case 'right':
                    setFocus('back-main')
                    break
                case 'left':
                    setFocus('back-series')
                    break
            }
        }
    })

    const { ref: backMainRef, focused: focusBackMain } = useFocusable({
        focusKey: "back-main",
        onFocus: (layout, props) => {

            handleScroll(backMainRef);

        },
        onArrowPress: (direction) => {
            switch (direction) {
                case 'down':
                    setFocus(`ep-${dataShape.episodes["1"][0].id}`)
                    break;
                case 'up':
                    setFocus(`movie-info`)
                    break
                case 'right':
                    setFocus('back-series')
                    break
                case 'left':
                    setFocus('back-categories')
                    break

            }
        }
    })



    const containerRef = useRef(null);


    const handleScroll = useCallback((focusedRef) => {
        if (containerRef.current && focusedRef.current) {
            focusedRef.current.scrollIntoView({
                behavior: 'smooth',
                block: 'center'
            });
        }
    }, []);

    const handleCategoryNavigation = useCallback((index, direction) => {
        if (direction === 'up' && index <= 0) {
            setFocus('back-series');
        }
        return true;
    }, []);

    useEffect(() => {
        setFocus("movie-info")
    }, [])

    return (
        <FocusContext.Provider value={focusKey}>

            <main className="gap-12 w-full min-h-screen h-full bg-[rgba(24,24,27,0.75)] flex flex-col justify-center items-center mx-auto" style={{
                background: `linear-gradient(to top, rgb(29, 29, 29) 0%, rgba(0, 0, 0, 0.5) 100%), url(${dataShape.info.backdrop_path[0]})`,
                backgroundSize: "cover",
                backgroundPosition: "center",
                backgroundRepeat: "no-repeat",
                backgroundAttachment: "fixed",
                minHeight: "100vh",
                margin: 0,
                zIndex: -1,
            }} ref={ref}>

                <div className="flex flex-row items-center justify-center gap-10 mt-20">

                    <section ref={movieRef} className="h-[65vh] aspect-[8.5_/_12]">
                        <img className="w-full bg-[rgba(245,245,245,0.3)] h-full rounded-xl border-0 border-solid border-transparent shadow-2x" src={dataShape.info.cover} alt={dataShape.info.name} />
                    </section>

                    <section className="flex flex-col w-1/6 gap-2 h-1/6" >
                        <h1 className="mb-2 text-2xl font-bold text-white ">{dataShape.info.name}</h1>
                        <p className="info-title">Plot:</p>
                        <span className=" info-text">{dataShape.info.plot}</span>
                        <p className="info-title">Genre:</p>
                        <span className="info-text">{dataShape.info.genre}</span>
                        <p className="info-title">Release Date:</p>
                        <span className="info-text">{dataShape.info.releaseDate}</span>
                        <p className="info-title">Rating:</p>
                        <span className="info-text"><StarRating rating={dataShape.info.rating_5based} /></span>
                    </section>
                </div>


                <section className="flex flex-col mx-4" ref={containerRef} >
                    <div className="flex flex-row gap-5 mb-5">
                        <button ref={backSeriesRef} className={`${focusBackSeries ? "shadow-lg shadow-red-500" : ""}`}>back to series</button>
                        <button ref={backCategoriesRef} className={`${focusBackCategories ? "shadow-lg shadow-red-500" : ""}`}>back to categories</button>
                        <button ref={backMainRef} className={`${focusBackMain ? "shadow-lg shadow-red-500" : ""}`}>back to main menu</button>
                    </div>
                    <h1 className="mt-5 text-4xl font-bold text-white">Seasons</h1>
                    <hr />
                    <div className="flex flex-col gap-5" >

                        {dataShape.seasons.map((season, index) => (
                            <section key={index} className="flex flex-col gap-2 mt-5">
                                <div className="flex flex-row gap-10">

                                    <h1 className="text-xl font-bold text-white">{season.name}</h1>
                                    <p className="text-white">{season.episode_count} Episodes</p>
                                </div>
                                <div className="grid grid-cols-6 gap-5 mt-5 ">
                                    {dataShape.episodes[(index + 1).toString()].map((ep, idx) => {
                                        return (
                                            <EpisodeCard ep={ep} onFocus={handleScroll} focusKey={`ep-${ep.id}`} key={ep.id} onArrowPress={(layout, props, details) => handleCategoryNavigation(index, details.direction)} />
                                        )
                                    })}
                                </div>
                                <hr />
                            </section>
                        ))}

                    </div>
                </section>

            </main>
        </FocusContext.Provider>

    )
}

export default InfoSeries

EpisodeCard

/* eslint-disable no-unused-vars */

import { useFocusable } from "@noriginmedia/norigin-spatial-navigation";

/* eslint-disable react/prop-types */
function EpisodeCard({ ep, onEnter, focusKey, onFocus, onArrowPress }) {
    const { ref, focused } = useFocusable({
        onEnterPress: onEnter,
        focusKey,
        onFocus: (layout, props) => {
            if (onFocus) {
                onFocus(ref);
            }
        },
        onArrowPress: (direction, layout, props) => {
            if (onArrowPress) {
                return onArrowPress(layout, props, { direction });
            }
            return true;
        }
    });

    return (

        <div ref={ref} className={`flex flex-col gap-2 px-4 py-2 rounded-md bg-gray-500/25 backdrop-blur-md ${focused ? "shadow-xl shadow-red-500 outline-4" : ""}`}>
            <img src={ep.info.movie_image} alt={ep.title} className="rounded-md" />
            <div className="flex flex-row gap-2 font-semibold text-white"><p>duration</p> <span className="text-red-500">{ep.info.duration}</span></div>
        </div>

    )
}

export default EpisodeCard
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant