Skip to content

Maintainence Update#302

Merged
n-ce merged 16 commits into
mainfrom
cumulus
May 27, 2025
Merged

Maintainence Update#302
n-ce merged 16 commits into
mainfrom
cumulus

Conversation

@n-ce
Copy link
Copy Markdown
Owner

@n-ce n-ce commented May 27, 2025

Summary by CodeRabbit

  • New Features

    • Added a shuffle feature to the queue, allowing users to randomize the order of queued items.
    • Introduced a "Listen" button in the video player dialog for direct audio playback.
  • Improvements

    • Sorting by title or artist in collections now toggles between ascending and descending order, with icons reflecting the current sort direction.
    • The UI now remembers and applies saved roundness and codec preferences.
    • The width of the collection selector and the stickiness of list headers have been enhanced for better usability.
    • Updated icons across the app for improved clarity and consistency.
    • Enhanced codec preference handling and playback settings for more intuitive control.
  • Localization

    • Updated English strings for clarity, such as "View Details" and "Add to Collection".
    • Added a new Polish localization string for PWA watch settings.
  • Style

    • Refined navigation and queue tool styles for improved appearance, especially on mobile devices.
    • Adjusted button displays and icon colors for better visual feedback.
    • Updated icon font mappings and styles for consistent visual presentation.
  • Documentation

    • Simplified setup instructions in the README for easier onboarding.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2025

Walkthrough

This update introduces a shuffle feature to the queue, enhances sorting controls with icon toggling and order reversal, and adds a "Listen" button to the video dialog. It also updates various icons and CSS styles, adjusts localization strings, streamlines development setup instructions, and refines logic for settings and theming.

Changes

File(s) Change Summary
src/scripts/queue.ts Added shuffle feature with UI button, DOM and store sync, shuffle persistence, and reshuffle on item removal.
src/scripts/list.ts Enhanced sorting: toggling icon state, reversing order, updating visual feedback for sort buttons.
src/components/WatchVideo.ts Added "Listen" button to video dialog, invoking player with current media ID and closing dialog.
src/components/ActionsMenu.ts, src/scripts/library.ts, index.html Updated icon classes for menu and action buttons.
src/stylesheets/remixicon.css Remapped icon classes, adjusted font-face syntax and weight, added new icons, and reorganized definitions.
src/components/ActionsMenu.css Increased width of collection selector.
src/components/Settings/app.ts, src/components/Settings/personalize.ts Refined settings logic: removed store assignment on mount and simplified roundness selector logic.
src/components/Settings/playback.ts Changed codec preference saving to use direct option value instead of index; improved logic clarity and default handling.
src/scripts/theme.ts Applied saved roundness setting directly to CSS variable outside settings component.
src/lib/libraryUtils.ts Synced "favorites" CSS class on list button container with current collection state.
src/locales/en.json Updated two localization strings for clarity.
src/modules/start.ts Applied saved codec and download format on startup; added <details> toggle logic in header with exception for icon clicks.
src/stylesheets/list.css Made list header sticky, adjusted button display styles, added .favorites modifier class hiding certain buttons and changing layout.
src/stylesheets/upcoming.css Tweaked icon colors and backgrounds for queue tool buttons; added new style for first child icon.
src/stylesheets/nav.css Adjusted nav padding, increased icon font size, hid nav text in portrait orientation.
src/stylesheets/search.css Removed trailing newline.
README.md Simplified development setup instructions by removing update step before installing dependencies.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant QueueUI
    participant Store
    participant DOM

    User->>QueueUI: Clicks Shuffle Button
    QueueUI->>QueueUI: Toggle "on" class, update saved "shuffle" state
    QueueUI->>QueueUI: Call shuffle()
    QueueUI->>DOM: Randomly reorder queue list children
    QueueUI->>Store: Update store.queue.list to match shuffled DOM order

    User->>QueueUI: Remove queue item (if shuffle is on)
    QueueUI->>QueueUI: Remove item from DOM and store
    QueueUI->>QueueUI: Call shuffle() to reshuffle
Loading
sequenceDiagram
    participant User
    participant ListUI
    participant Store
    participant DB

    User->>ListUI: Clicks Sort By Title/Author
    ListUI->>ListUI: Sort collection array by field
    ListUI->>ListUI: Toggle icon between asc/desc, reverse array if needed
    ListUI->>DB: Save sorted collection
    ListUI->>ListUI: Render updated list
Loading
sequenceDiagram
    participant User
    participant WatchVideoDialog
    participant Player

    User->>WatchVideoDialog: Clicks "Listen" button
    WatchVideoDialog->>Player: Call player(store.actionsMenu.id)
    WatchVideoDialog->>WatchVideoDialog: Close dialog
Loading

Possibly related PRs

Poem

🐇
Shuffle and sort, with a hop and a spin,
New icons and buttons, where do I begin?
"Listen" now beckons, a click starts the song,
With sticky headers, the lists grow strong.
A rabbit’s delight in code’s gentle spring—
Here’s to the changes that new features bring!


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d1d408 and 15e988d.

📒 Files selected for processing (2)
  • src/locales/ar.json (1 hunks)
  • src/locales/pl.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/locales/pl.json
🔇 Additional comments (1)
src/locales/ar.json (1)

2-169: Consistent formatting update across locale files

Reformatted the file to use 4-space indentation and added a trailing newline without modifying any translation keys or values, aligning ar.json with other locale JSON files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/components/Settings/personalize.ts (1)

42-43: Simplify redundant conditional logic.

The current logic has redundant checking. Since you're inside an if (getSaved('roundness')) block, the || '0.4rem' fallback will never execute because getSaved('roundness') is guaranteed to be truthy.

Consider simplifying to handle both cases more clearly:

-if (getSaved('roundness'))
-  target.value = getSaved('roundness') || '0.4rem';
+target.value = getSaved('roundness') || '0.4rem';

This achieves the same result with cleaner logic - set the saved value if it exists, otherwise use the default.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e5b82be and 84d01cd.

📒 Files selected for processing (2)
  • src/components/Settings/personalize.ts (1 hunks)
  • src/scripts/theme.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/components/Settings/personalize.ts (1)
src/lib/store.ts (1)
  • getSaved (3-3)
src/scripts/theme.ts (1)
src/lib/store.ts (1)
  • getSaved (3-3)

Comment thread src/scripts/theme.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
src/stylesheets/list.css (1)

36-36: CSS specificity pattern suggests potential underlying specificity conflicts.

The systematic addition of !important declarations to existing display: block rules suggests there may be competing CSS rules with higher specificity. Consider investigating the root cause of these specificity conflicts to avoid relying heavily on !important.

While the current approach works, consider reviewing the CSS architecture to reduce dependency on !important declarations for better maintainability.

Also applies to: 47-47, 86-86

src/modules/start.ts (1)

124-132: Improve the details toggle logic for better maintainability.

The current implementation manually manages the open attribute, but the logic only handles closing when already open. This could lead to inconsistent behavior.

Consider this more robust implementation:

-  (document.querySelectorAll('header details') as NodeListOf<HTMLDetailsElement>).forEach(d => {
-    d.addEventListener('click', (e) => {
-      const elm = e.target as HTMLElement;
-      if (elm.matches('i'))
-        return;
-      if (d.open)
-        d.removeAttribute('open');
-    })
-  })
+  (document.querySelectorAll('header details') as NodeListOf<HTMLDetailsElement>).forEach(details => {
+    details.addEventListener('click', (e) => {
+      const target = e.target as HTMLElement;
+      if (target.matches('i')) {
+        e.preventDefault();
+        return;
+      }
+      // Let the browser handle the default toggle behavior
+      // but you can add custom logic here if needed
+    })
+  })

Alternatively, if you need custom toggle behavior, make it more explicit:

-  (document.querySelectorAll('header details') as NodeListOf<HTMLDetailsElement>).forEach(d => {
-    d.addEventListener('click', (e) => {
-      const elm = e.target as HTMLElement;
-      if (elm.matches('i'))
-        return;
-      if (d.open)
-        d.removeAttribute('open');
-    })
-  })
+  (document.querySelectorAll('header details') as NodeListOf<HTMLDetailsElement>).forEach(details => {
+    details.addEventListener('click', (e) => {
+      const target = e.target as HTMLElement;
+      if (target.matches('i')) {
+        e.preventDefault();
+        return;
+      }
+      e.preventDefault();
+      details.toggleAttribute('open');
+    })
+  })
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74f2de4 and a983b33.

📒 Files selected for processing (9)
  • README.md (1 hunks)
  • src/components/ActionsMenu.css (1 hunks)
  • src/components/Settings/app.ts (1 hunks)
  • src/components/Settings/playback.ts (1 hunks)
  • src/lib/libraryUtils.ts (1 hunks)
  • src/locales/en.json (1 hunks)
  • src/modules/start.ts (2 hunks)
  • src/stylesheets/header.css (1 hunks)
  • src/stylesheets/list.css (3 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/components/ActionsMenu.css
  • src/locales/en.json
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/lib/libraryUtils.ts (1)
src/lib/dom.ts (1)
  • listBtnsContainer (35-35)
src/modules/start.ts (1)
src/lib/store.ts (2)
  • getSaved (3-3)
  • store (5-108)
src/components/Settings/playback.ts (2)
src/lib/utils.ts (2)
  • save (13-13)
  • removeSaved (15-15)
src/lib/store.ts (1)
  • store (5-108)
🪛 markdownlint-cli2 (0.17.2)
README.md

73-73: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

🔇 Additional comments (5)
src/stylesheets/list.css (1)

51-65: Well-structured favorites modifier class implementation.

The .favorites modifier correctly implements the business logic for the favorites collection:

  • Shows all list items with block !important display
  • Appropriately hides management buttons (delete, rename, radio, import, subscribe, viewOnYT) that don't apply to the favorites collection

The CSS structure aligns well with the JavaScript logic in libraryUtils.ts that manages this class.

src/lib/libraryUtils.ts (1)

111-116: Excellent coordination between CSS and JavaScript for favorites collection handling.

The logic correctly manages the "favorites" class state:

  • Removes the class when navigating away from favorites collection
  • Adds the class when navigating to favorites collection
  • Follows a good pattern of setting base class first (line 109), then applying specific modifiers

This implementation properly coordinates with the CSS changes in list.css to control button visibility for the favorites collection.

src/stylesheets/header.css (1)

2-3:

Details

✅ Verification successful

Good improvement for header visibility and layering.

The change from relative to sticky positioning with z-index: 20 will keep the header visible during scrolling while ensuring proper element layering. This aligns well with the mentioned event listeners for <details> elements.

Please verify that the z-index value doesn't conflict with other elements in the layout hierarchy:


🏁 Script executed:

#!/bin/bash
# Description: Check for other z-index values in CSS files to ensure proper layering hierarchy
rg -A 2 -B 2 "z-index:" --type css

Length of output: 1983


Z-index hierarchy verified: no conflicts detected.

Header’s z-index: 20 sits above all other components (Snackbar 9, UpdatePrompt 4, Search 3/1, StreamItem 2/0), so this change is safe.

Approving these CSS updates.

README.md (1)

72-74:

Details

✅ Verification successful

Simplified setup process looks good.

The removal of the npm run update step streamlines the development setup. The change aligns with the broader effort to optimize initialization processes mentioned in the AI summary.

Please verify that removing npm run update doesn't break the setup process:


🏁 Script executed:

#!/bin/bash
# Description: Check if npm run update script exists and what it does
if [ -f "package.json" ]; then
  echo "Checking for update script in package.json:"
  jq '.scripts.update // "Script not found"' package.json
else
  echo "package.json not found"
fi

Length of output: 199


Removal of npm run update Confirmed Safe

Checked package.json and found no update script, so removing the npm run update step will not omit any required setup. The streamlined install command is correct—approving these README changes.

🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

73-73: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

src/components/Settings/app.ts (1)

93-96: Good separation of concerns by removing redundant store assignment.

The removal of store.downloadFormat = savedDownloadFormat as 'opus'; during component mount is appropriate. According to the AI summary, this initialization is now handled centrally in src/modules/start.ts, which prevents redundant or conflicting state assignments and improves code organization.

Comment on lines +37 to 44
const c = e.target.value as '' | 'opus' | 'aac';
if (c)
save('codec', c)
else
removeSaved('codec');

store.player.codec = e.target.value as 'any';
store.player.codec = c || 'any';
quickSwitch();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix inconsistency between handler and onmount logic.

The refactor to use e.target.value directly instead of selectedIndex is cleaner and more maintainable. However, there's an inconsistency: the handler now uses values ('opus', 'aac', '') while the onmount function still uses selectedIndex logic.

The onmount function (lines 46-53) should be updated to match the new value-based approach:

    onmount: async (target) => {
      const codecSaved = getSaved('codec');
-     target.selectedIndex = codecSaved ?
-       parseInt(codecSaved) :
-       ((await store.player.supportsOpus) ? 0 : 1);
+     if (codecSaved) {
+       target.value = codecSaved;
+     } else {
+       target.value = (await store.player.supportsOpus) ? 'opus' : 'aac';
+     }

-     store.player.codec = target.value as 'any';
+     store.player.codec = target.value as 'opus' | 'aac' || 'any';
    },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const c = e.target.value as '' | 'opus' | 'aac';
if (c)
save('codec', c)
else
removeSaved('codec');
store.player.codec = e.target.value as 'any';
store.player.codec = c || 'any';
quickSwitch();
onmount: async (target) => {
const codecSaved = getSaved('codec');
- target.selectedIndex = codecSaved ?
- parseInt(codecSaved) :
- ((await store.player.supportsOpus) ? 0 : 1);
+ if (codecSaved) {
+ target.value = codecSaved;
+ } else {
+ target.value = (await store.player.supportsOpus) ? 'opus' : 'aac';
+ }
- store.player.codec = target.value as 'any';
+ store.player.codec = target.value as 'opus' | 'aac' || 'any';
},
🤖 Prompt for AI Agents
In src/components/Settings/playback.ts around lines 37 to 44, the event handler
uses e.target.value directly for codec selection, but the onmount function
(lines 46-53) still relies on selectedIndex, causing inconsistency. Update the
onmount function to use the same value-based approach by reading and setting the
codec using the string values ('', 'opus', 'aac') instead of selectedIndex,
ensuring both parts handle codec selection consistently.

Comment thread src/modules/start.ts
Comment on lines +57 to +59
const savedDownloadFormat = getSaved('dlFormat');
if (savedDownloadFormat)
store.downloadFormat = savedDownloadFormat as 'opus';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add validation for saved download format.

Similar to the codec handling, the download format should be validated before assignment to prevent invalid values from being set.

Apply this diff to add validation:

-  const savedDownloadFormat = getSaved('dlFormat');
-  if (savedDownloadFormat)
-    store.downloadFormat = savedDownloadFormat as 'opus';
+  const savedDownloadFormat = getSaved('dlFormat');
+  const validFormats = ['opus', 'wav', 'mp3', 'ogg'] as const;
+  if (savedDownloadFormat && validFormats.includes(savedDownloadFormat as any))
+    store.downloadFormat = savedDownloadFormat as typeof store.downloadFormat;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const savedDownloadFormat = getSaved('dlFormat');
if (savedDownloadFormat)
store.downloadFormat = savedDownloadFormat as 'opus';
const savedDownloadFormat = getSaved('dlFormat');
const validFormats = ['opus', 'wav', 'mp3', 'ogg'] as const;
if (savedDownloadFormat && validFormats.includes(savedDownloadFormat as any))
store.downloadFormat = savedDownloadFormat as typeof store.downloadFormat;
🤖 Prompt for AI Agents
In src/modules/start.ts around lines 57 to 59, the saved download format is
assigned directly without validation, which risks setting invalid values. Add a
validation step to check if the savedDownloadFormat is one of the allowed
formats (e.g., 'opus') before assigning it to store.downloadFormat. If it is not
valid, do not assign it or handle it appropriately to ensure only valid download
formats are used.

Comment thread src/modules/start.ts

// codec handling

const codecSaved = getSaved('codec') as 'opus';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect type assertion.

The type assertion as 'opus' is incorrect since the saved codec can be any of the valid codec types or null/undefined.

Apply this diff to fix the type assertion:

-  const codecSaved = getSaved('codec') as 'opus';
+  const codecSaved = getSaved('codec') as 'opus' | 'aac' | 'any' | null;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const codecSaved = getSaved('codec') as 'opus';
const codecSaved = getSaved('codec') as 'opus' | 'aac' | 'any' | null;
🤖 Prompt for AI Agents
In src/modules/start.ts at line 53, the type assertion 'as 'opus'' is incorrect
because the saved codec can be any valid codec type or null/undefined. Remove
the incorrect assertion and instead use a proper type that reflects all possible
codec values or null/undefined, such as a union type or the original return type
of getSaved, to accurately represent the saved codec variable.

Comment thread src/modules/start.ts
Comment on lines +54 to +55
store.player.codec = codecSaved ||
((await store.player.supportsOpus) ? 'opus' : 'aac');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve codec fallback logic and error handling.

The current logic has a potential issue: if codecSaved is a non-empty string but not a valid codec value, it will still be assigned. Consider adding validation.

Apply this diff to improve the logic:

-  store.player.codec = codecSaved ||
-    ((await store.player.supportsOpus) ? 'opus' : 'aac');
+  const validCodecs = ['opus', 'aac', 'any'] as const;
+  store.player.codec = (codecSaved && validCodecs.includes(codecSaved as any)) 
+    ? codecSaved as typeof store.player.codec
+    : ((await store.player.supportsOpus) ? 'opus' : 'aac');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
store.player.codec = codecSaved ||
((await store.player.supportsOpus) ? 'opus' : 'aac');
const validCodecs = ['opus', 'aac', 'any'] as const;
store.player.codec = (codecSaved && validCodecs.includes(codecSaved as any))
? codecSaved as typeof store.player.codec
: ((await store.player.supportsOpus) ? 'opus' : 'aac');
🤖 Prompt for AI Agents
In src/modules/start.ts around lines 54 to 55, the assignment of
store.player.codec directly uses codecSaved without validating if it is a valid
codec. To fix this, add a validation step to check if codecSaved is a valid
codec before assigning it. If codecSaved is invalid or falsy, then fallback to
checking store.player.supportsOpus and assign 'opus' or 'aac' accordingly. This
ensures only valid codec values are assigned and improves error handling.

Comment thread src/modules/start.ts

const savedDownloadFormat = getSaved('dlFormat');
if (savedDownloadFormat)
store.downloadFormat = savedDownloadFormat as 'opus';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect type assertion for download format.

The type assertion as 'opus' is incorrect since the saved download format can be any of the valid format types or null/undefined.

Apply this diff to fix the type assertion:

-    store.downloadFormat = savedDownloadFormat as 'opus';
+    store.downloadFormat = savedDownloadFormat as 'opus' | 'wav' | 'mp3' | 'ogg';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
store.downloadFormat = savedDownloadFormat as 'opus';
store.downloadFormat = savedDownloadFormat as 'opus' | 'wav' | 'mp3' | 'ogg';
🤖 Prompt for AI Agents
In src/modules/start.ts at line 59, the type assertion 'as 'opus'' is incorrect
because savedDownloadFormat can be any valid format type or null/undefined.
Remove the incorrect assertion and instead ensure that store.downloadFormat is
assigned with the correct type that accommodates all valid formats or handle
null/undefined appropriately, such as by using a union type or a type guard.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/scripts/queue.ts (1)

230-231: Add safety check for shuffle after item removal.

While the logic is sound, consider adding a safety check to prevent unnecessary shuffling when the queue is empty or has only one item.

Apply this diff to add the safety check:

-  if (getSaved('shuffle'))
-    shuffle();
+  if (getSaved('shuffle') && queuelist.children.length > 1)
+    shuffle();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a983b33 and 7c6de30.

📒 Files selected for processing (2)
  • src/scripts/queue.ts (3 hunks)
  • src/stylesheets/upcoming.css (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/stylesheets/upcoming.css
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/scripts/queue.ts (3)
src/lib/dom.ts (1)
  • queuelist (21-21)
src/lib/store.ts (2)
  • store (5-108)
  • getSaved (3-3)
src/lib/utils.ts (2)
  • removeSaved (15-15)
  • save (13-13)
🔇 Additional comments (2)
src/scripts/queue.ts (2)

12-12: LGTM: Variable declaration follows existing pattern.

The shuffleBtn variable declaration is consistent with other button variables in the file.


50-69: LGTM: Shuffle button implementation follows established patterns.

The button implementation correctly:

  • Follows the same pattern as other queue tool buttons
  • Handles state persistence with localStorage
  • Integrates with the existing template structure
  • Provides appropriate user feedback

Comment thread src/scripts/queue.ts
Comment on lines +39 to +47
function shuffle() {
for (let i = queuelist.children.length; i >= 0; i--)
queuelist.appendChild(queuelist.children[Math.random() * i | 0]);

store.queue.list.length = 0;

for (const item of queuelist.children)
store.queue.list.push((item as HTMLElement).dataset.id || '');
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix the shuffle algorithm and improve performance.

The current shuffle implementation has a critical bug and performance issues:

  1. Algorithm bug: The loop condition i >= 0 causes an extra iteration when i = 0, where Math.random() * 0 always equals 0, potentially causing incorrect behavior.

  2. Performance issue: The algorithm is O(n²) due to repeated DOM manipulations in the loop.

Apply this diff to fix the algorithm and improve performance:

 function shuffle() {
-  for (let i = queuelist.children.length; i >= 0; i--)
-    queuelist.appendChild(queuelist.children[Math.random() * i | 0]);
+  // Convert to array for efficient shuffling
+  const items = Array.from(queuelist.children);
+  
+  // Fisher-Yates shuffle algorithm
+  for (let i = items.length - 1; i > 0; i--) {
+    const j = Math.floor(Math.random() * (i + 1));
+    [items[i], items[j]] = [items[j], items[i]];
+  }
+  
+  // Clear and re-append in shuffled order
+  queuelist.innerHTML = '';
+  items.forEach(item => queuelist.appendChild(item));

   store.queue.list.length = 0;

   for (const item of queuelist.children)
     store.queue.list.push((item as HTMLElement).dataset.id || '');
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function shuffle() {
for (let i = queuelist.children.length; i >= 0; i--)
queuelist.appendChild(queuelist.children[Math.random() * i | 0]);
store.queue.list.length = 0;
for (const item of queuelist.children)
store.queue.list.push((item as HTMLElement).dataset.id || '');
}
function shuffle() {
// Convert to array for efficient shuffling
const items = Array.from(queuelist.children);
// Fisher-Yates shuffle algorithm
for (let i = items.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[items[i], items[j]] = [items[j], items[i]];
}
// Clear and re-append in shuffled order
queuelist.innerHTML = '';
items.forEach(item => queuelist.appendChild(item));
store.queue.list.length = 0;
for (const item of queuelist.children)
store.queue.list.push((item as HTMLElement).dataset.id || '');
}
🤖 Prompt for AI Agents
In src/scripts/queue.ts around lines 39 to 47, the shuffle function has a bug
with the loop condition allowing an extra iteration at i=0 and suffers from poor
performance due to repeated DOM manipulations inside the loop. Fix this by
implementing the Fisher-Yates shuffle algorithm on an array copy of the children
elements to avoid direct DOM manipulation in the loop, then re-append the
shuffled elements to the DOM once after the shuffle completes. This will correct
the algorithm and improve performance to O(n).

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/components/WatchVideo.ts (1)

181-184: Consider preserving playback position when switching to audio mode.

The Listen button provides a useful feature to switch from video to audio-only mode. However, the current implementation may lose the playback position since close() pauses the current audio/video and player() starts fresh playback.

Consider preserving the current playback position:

-      <button @click=${() => {
-      player(store.actionsMenu.id);
-      close();
-    }}>Listen</button>
+      <button @click=${() => {
+      const currentTime = video.currentTime;
+      close();
+      player(store.actionsMenu.id).then(() => {
+        // Set the playback position after player loads
+        const audioElement = document.querySelector('audio');
+        if (audioElement) audioElement.currentTime = currentTime;
+      });
+    }}>Listen</button>

Alternatively, you could store the current time in the store before closing and have the player function check for and apply any stored position.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c6de30 and 313146f.

📒 Files selected for processing (1)
  • src/components/WatchVideo.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/components/WatchVideo.ts (2)
src/lib/player.ts (1)
  • player (8-100)
src/lib/store.ts (1)
  • store (5-108)
🔇 Additional comments (1)
src/components/WatchVideo.ts (1)

3-3: LGTM! Import is necessary for the new Listen functionality.

The import of the player function is correctly added to support the new Listen button feature.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/stylesheets/header.css (1)

2-4: Enable sticky header with correct stacking order
Changing position to sticky with top: 0 and adding z-index: 20 ensures the header stays visible and layers above other elements when scrolling. As a follow-up, consider extracting the magic number into a CSS variable (e.g., --z-header: 20;) so you can maintain consistent stacking values across components.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 313146f and 2ea5759.

📒 Files selected for processing (2)
  • src/modules/start.ts (2 hunks)
  • src/stylesheets/header.css (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/modules/start.ts
🔇 Additional comments (1)
src/stylesheets/header.css (1)

7-7: Validate theme background variable
Setting background: var(--bg) ties the header’s background to your theme. Please confirm that --bg is defined for all theme variants (light/dark) to prevent unexpected transparent backgrounds. You might also provide a fallback color, for example:

background: var(--bg, #fff);

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/stylesheets/nav.css (1)

29-29: Ensure cross-browser compatibility for dvh units
Using the dvh unit can yield inconsistent results on browsers that don’t fully support the CSS Viewport Units Level 4 spec. Add a fallback using a more widely supported unit (e.g., percentage or vh) before the dvh declaration.

Proposed diff:

 nav {
   width: 100%;
-  padding: 1.5dvh 0 2.5dvh;
+  /* Fallback for browsers without dvh support */
+  padding: 2% 0;
+  /* Use dvh for more accurate viewport height on modern browsers */
+  padding: 1.5dvh 0 2.5dvh;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ea5759 and b78340d.

📒 Files selected for processing (3)
  • src/stylesheets/header.css (2 hunks)
  • src/stylesheets/nav.css (2 hunks)
  • src/stylesheets/search.css (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/stylesheets/search.css
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/stylesheets/header.css
🔇 Additional comments (1)
src/stylesheets/nav.css (1)

39-39: Icon font-size increase enhances touch targets
Bumping the icon size from 1.2rem to 1.5rem improves readability and tap targets on small screens.

Comment thread src/stylesheets/nav.css
margin: 0;
padding: 0;
font-size: 0.8rem;
display: none;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Preserve text labels for accessibility
Hiding the <p> elements with display: none removes them from assistive technologies. Instead, apply a “visually hidden” pattern or ensure each <a> has an aria-label or title attribute so screen readers can announce the label.

Example visually-hidden utility (add near top of your stylesheet):

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

Then update:

 nav a {
   /* ... */
-  p {
-    display: none;
-  }
+  p {
+    @extend .sr-only; /* Keeps text available for screen readers */
+  }
 }
🤖 Prompt for AI Agents
In src/stylesheets/nav.css at line 43, replace the use of 'display: none' on the
<p> elements with a visually hidden CSS class to preserve accessibility. Add a
'.sr-only' class near the top of the stylesheet with the recommended styles for
visually hiding content but keeping it accessible to screen readers. Then apply
this '.sr-only' class to the <p> elements instead of using 'display: none'.
Alternatively, ensure each <a> element has an appropriate 'aria-label' or
'title' attribute to provide accessible labels.

@n-ce n-ce linked an issue May 27, 2025 that may be closed by this pull request
weblate and others added 2 commits May 27, 2025 17:06
Currently translated at 94.0% (157 of 167 strings)

Translation: ytify/web
Translate-URL: https://hosted.weblate.org/projects/ytify/web/ar/
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/scripts/list.ts (1)

119-133: Enhanced sorting with robust icon state management.

The sorting logic enhancement effectively implements icon toggling and order reversal functionality. The code correctly:

  1. Constructs appropriate class prefixes for different field types
  2. Toggles between ascending/descending states
  3. Reverses the collection array for descending order
  4. Persists changes using the existing saveDB utility

The implementation is well-integrated with the icon updates in index.html and provides good user feedback for sorting operations.

However, consider adding error handling for edge cases:

+ if (!ico) {
+   console.warn(`Sort icon not found for field: ${field}`);
+   return;
+ }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b78340d and 6d1d408.

⛔ Files ignored due to path filters (1)
  • public/remixicon.woff2 is excluded by !**/*.woff2
📒 Files selected for processing (7)
  • index.html (2 hunks)
  • src/components/ActionsMenu.ts (3 hunks)
  • src/scripts/library.ts (1 hunks)
  • src/scripts/list.ts (2 hunks)
  • src/scripts/queue.ts (4 hunks)
  • src/stylesheets/list.css (4 hunks)
  • src/stylesheets/remixicon.css (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • src/components/ActionsMenu.ts
  • src/scripts/library.ts
  • src/stylesheets/remixicon.css
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/stylesheets/list.css
  • src/scripts/queue.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/scripts/list.ts (1)
src/lib/libraryUtils.ts (1)
  • saveDB (10-13)
🔇 Additional comments (4)
index.html (3)

272-272: Icon update improves semantic clarity.

The change from ri-subtract-line to ri-indeterminate-circle-line for the remove button provides better visual representation of the removal action, making it more semantically appropriate for list item removal functionality.


290-290: Enhanced sort button with appropriate alphabetic icon.

The change from ri-draggable to ri-sort-alphabet-asc correctly represents the alphabetic sorting functionality for titles. This icon choice aligns with the enhanced sorting logic in src/scripts/list.ts that toggles between ascending and descending states.


293-293: Consistent sort icon for artist sorting.

The change from ri-draggable to ri-sort-asc provides appropriate visual representation for artist sorting functionality, maintaining consistency with the title sort button while using a generic ascending sort icon suitable for non-alphabetic content.

src/scripts/list.ts (1)

104-106: Code style improvement with consistent braces.

Adding braces around the single-line else if block improves code consistency and readability, following best practices for maintainable code structure.

@n-ce n-ce merged commit 568dbef into main May 27, 2025
2 checks passed
@n-ce n-ce deleted the cumulus branch May 27, 2025 17:53
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

Successfully merging this pull request may close these issues.

Add spacing at bottom

3 participants