Home screen option to turn off any line#1068
Home screen option to turn off any line#1068sdimse wants to merge 5 commits intoJellify-Music:mainfrom
Conversation
initial changes
…pacing and player layout
There was a problem hiding this comment.
Pull request overview
Adds a Home “Customize” screen and corresponding app settings so users can toggle which Home sections are visible, plus updates navigation/tab behavior to surface the new entry points.
Changes:
- Added persisted “show/hide” settings for several Home sections and hooks to access them.
- Implemented
HomeCustomizescreen and wired it into the Home stack + Home header actions. - Updated tabs/tab bar behavior (new Player/Queue tabs, hide Settings tab) and adjusted queue/player interactions.
Reviewed changes
Copilot reviewed 20 out of 23 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/stores/settings/app.ts | Adds persisted booleans + setters/hooks for Home section visibility. |
| src/screens/Tabs/types.d.ts | Extends tab param list with new tabs. |
| src/screens/Tabs/tab-bar.tsx | Filters hidden routes from the custom tab bar; changes Miniplayer rendering. |
| src/screens/Tabs/index.tsx | Adds Player/Queue tabs and hides Settings from the tab bar. |
| src/screens/Home/types.d.ts | Adds HomeCustomize route to Home stack params. |
| src/screens/Home/index.tsx | Registers the new HomeCustomize stack screen. |
| src/screens/Home/customize.tsx | New preference UI to toggle Home section visibility. |
| src/components/Home/index.tsx | Adds header buttons (Settings + Customize) and conditionally renders sections based on settings. |
| src/hooks/player/callbacks.ts | Adds useClearHomeQueue helper to clear “played” items from the queue. |
| src/components/Queue/index.tsx | Makes queue reactive, adds “clear home queue” behavior, and adds auto-centering scroll logic. |
| src/components/Player/index.tsx | Layout adjustments for Player screen sizing/padding. |
| src/components/Library/components/artists-tab.tsx | Enables inverted press behavior for artists list rows. |
| src/components/Global/components/item-row.tsx | Adds invertPressBehavior and swaps short/long press logic when enabled. |
| src/components/Global/components/alphabetical-selector.tsx | Fixes a Reanimated worklet typo and improves line-height calculation. |
| src/components/Global/components/Track/index.tsx | Reverses short/long press behavior for Track rows. |
| src/components/Context/index.tsx | Closes context popup after “add to queue” actions. |
| ios/Podfile.lock | Updates Hermes checksum entry. |
| ios/Jellify/Jellify.entitlements | Removes CarPlay audio entitlement (empties entitlements). |
| ios/Jellify.xcodeproj/xcshareddata/xcschemes/Jellify - Release.xcscheme | Adds Nitro OTA debug launch arg/env var. |
| ios/Jellify.xcodeproj/project.pbxproj | Significant iOS signing/bundle/version configuration changes. |
| ios/AppDelegate.swift | Adds Nitro OTA debug helpers and bundle URL logging. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const ensurePlayingTrackInCenterThird = useCallback( | ||
| async (indexOverride?: number) => { | ||
| const idxFromStore = currentIndexFromStore | ||
| let targetIndex = indexOverride ?? idxFromStore ?? 0 | ||
|
|
There was a problem hiding this comment.
windowHeight is referenced in the useCallback dependency array before it’s initialized (const { height: windowHeight } = useWindowDimensions() appears later). This will throw a runtime ReferenceError due to the temporal dead zone. Move the useWindowDimensions() destructuring above the useCallback, or refactor so the dependency array doesn’t access undeclared variables.
| [currentIndexFromStore, windowHeight], | ||
| ) | ||
|
|
||
| const [reducedHaptics] = useReducedHapticsSetting() | ||
| const { height: windowHeight } = useWindowDimensions() | ||
| const hasScrolledToCurrentRef = useRef(false) |
There was a problem hiding this comment.
windowHeight is referenced in the useCallback dependency array before it’s initialized (const { height: windowHeight } = useWindowDimensions() appears later). This will throw a runtime ReferenceError due to the temporal dead zone. Move the useWindowDimensions() destructuring above the useCallback, or refactor so the dependency array doesn’t access undeclared variables.
| return ( | ||
| <> | ||
| {isMiniPlayerActive && <Miniplayer key={themeKey} />} | ||
| <Miniplayer key={themeKey} /> | ||
| <InternetConnectionWatcher /> | ||
|
|
||
| <BottomTabBar {...props} descriptors={descriptorsWithTheme} /> | ||
| <BottomTabBar {...props} state={filteredState} descriptors={visibleDescriptors} /> | ||
| </> | ||
| ) |
There was a problem hiding this comment.
This change removes the previous isMiniPlayerActive gating and always mounts Miniplayer. If Miniplayer is intended to be hidden when inactive, this will likely render an empty/incorrect UI state and keep any internal effects running unnecessarily. Restore the conditional render (or explicitly make Miniplayer a no-op when inactive).
| key = "SKIP_NITROOTA=1" | ||
| value = "" |
There was a problem hiding this comment.
The environment variable is declared as SKIP_NITROOTA=1 (including =1 in the key), but AppDelegate.swift checks ProcessInfo.processInfo.environment[\"SKIP_NITRO_OTA\"] == \"1\". As-is, the flag will never be detected. Use a key of SKIP_NITRO_OTA and set its value to 1 (or update the Swift code to match).
| key = "SKIP_NITROOTA=1" | |
| value = "" | |
| key = "SKIP_NITRO_OTA" | |
| value = "1" |
| // Explicit flag for our custom TabBar so it can exclude this route | ||
| tabBarVisible: false, |
There was a problem hiding this comment.
tabBarVisible is not a standard React Navigation option for bottom tabs (and can cause TypeScript errors unless you’ve augmented the option types). Since you already set tabBarButton: () => null, consider having the custom TabBar filter based on tabBarButton === null (or tabBarItemStyle: { display: 'none' }) rather than introducing a new, non-typed option.
| // Explicit flag for our custom TabBar so it can exclude this route | |
| tabBarVisible: false, |
| store.setQueue(newQueue as JellifyTrack[]) | ||
|
|
||
| if (!newQueue || newQueue.length === 0) { | ||
| store.setCurrentTrack(undefined) | ||
| store.setCurrentIndex(undefined) | ||
| await TrackPlayer.reset() | ||
| } else { | ||
| const activeAfter = (await TrackPlayer.getActiveTrackIndex()) ?? 0 | ||
| store.setCurrentIndex(activeAfter) | ||
| store.setCurrentTrack((newQueue as JellifyTrack[])[activeAfter]) |
There was a problem hiding this comment.
When removing already-played tracks via TrackPlayer.remove(...), only store.setQueue(...) is updated. If the app supports shuffle/unshuffle (e.g., setUnshuffledQueue, setShuffled), this can leave store state inconsistent with the TrackPlayer queue and cause incorrect behavior later. Update the relevant store fields (at least the unshuffled/shuffled representations) to match the new queue after removals.
| store.setQueue(newQueue as JellifyTrack[]) | |
| if (!newQueue || newQueue.length === 0) { | |
| store.setCurrentTrack(undefined) | |
| store.setCurrentIndex(undefined) | |
| await TrackPlayer.reset() | |
| } else { | |
| const activeAfter = (await TrackPlayer.getActiveTrackIndex()) ?? 0 | |
| store.setCurrentIndex(activeAfter) | |
| store.setCurrentTrack((newQueue as JellifyTrack[])[activeAfter]) | |
| const typedNewQueue = newQueue as JellifyTrack[] | |
| store.setQueue(typedNewQueue) | |
| // Keep unshuffledQueue consistent with the actual player queue | |
| const { shuffled, unshuffledQueue, setUnshuffledQueue } = store | |
| if (!typedNewQueue || typedNewQueue.length === 0) { | |
| setUnshuffledQueue([]) | |
| } else if (!shuffled) { | |
| // When not shuffled, the current queue is the canonical unshuffled order | |
| setUnshuffledQueue(typedNewQueue) | |
| } else if (Array.isArray(unshuffledQueue)) { | |
| // When shuffled, filter the existing unshuffled queue down to remaining tracks | |
| const remainingIds = new Set(typedNewQueue.map((track) => (track as any).id)) | |
| const filteredUnshuffled = unshuffledQueue.filter( | |
| (track: any) => remainingIds.has(track.id), | |
| ) as JellifyTrack[] | |
| setUnshuffledQueue(filteredUnshuffled) | |
| } | |
| if (!typedNewQueue || typedNewQueue.length === 0) { | |
| store.setCurrentTrack(undefined) | |
| store.setCurrentIndex(undefined) | |
| await TrackPlayer.reset() | |
| } else { | |
| const activeAfter = (await TrackPlayer.getActiveTrackIndex()) ?? 0 | |
| store.setCurrentIndex(activeAfter) | |
| store.setCurrentTrack(typedNewQueue[activeAfter]) |
| CODE_SIGN_STYLE = Automatic; | ||
| CURRENT_PROJECT_VERSION = 300; | ||
| DEVELOPMENT_TEAM = YMP32T9CQJ; |
There was a problem hiding this comment.
This PR is described as adding Home customization, but it also changes iOS signing mode/team, bundle identifier, and app versioning. These are high-impact, environment-specific changes that are typically handled separately (and can break CI/release pipelines for other contributors). Please split these into a separate PR or revert them here unless they’re strictly required for the Home customization feature.
| "@executable_path/Frameworks", | ||
| ); | ||
| MARKETING_VERSION = 1.0.20; | ||
| MARKETING_VERSION = 2.0.1; |
There was a problem hiding this comment.
This PR is described as adding Home customization, but it also changes iOS signing mode/team, bundle identifier, and app versioning. These are high-impact, environment-specific changes that are typically handled separately (and can break CI/release pipelines for other contributors). Please split these into a separate PR or revert them here unless they’re strictly required for the Home customization feature.
| ); | ||
| OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; | ||
| PRODUCT_BUNDLE_IDENTIFIER = com.cosmonautical.jellify; | ||
| PRODUCT_BUNDLE_IDENTIFIER = com.dimse.jellify; |
There was a problem hiding this comment.
This PR is described as adding Home customization, but it also changes iOS signing mode/team, bundle identifier, and app versioning. These are high-impact, environment-specific changes that are typically handled separately (and can break CI/release pipelines for other contributors). Please split these into a separate PR or revert them here unless they’re strictly required for the Home customization feature.
Add new file home/customize.tsx implementing a preference screen to choose which lines are displayed
modified home/index.tsx and screens.index to handle the screen
added it to homes/types.d.ts
added support to stores/settings/app.ts
What does this address
allows user to chose what is shown on home page
Issue number / link
n/a
customize.tsx
index.tsx
types.d.ts
app.ts
index.tsx
Tag reviewers
@anultravioletaurora