Skip to content

Enable screenshot both to file and clipboard simultaneously#1094

Merged
VampireChicken12 merged 1 commit into
YouTube-Enhancer:devfrom
azatoth:add-screenshot-both-option
Nov 29, 2025
Merged

Enable screenshot both to file and clipboard simultaneously#1094
VampireChicken12 merged 1 commit into
YouTube-Enhancer:devfrom
azatoth:add-screenshot-both-option

Conversation

@azatoth
Copy link
Copy Markdown
Contributor

@azatoth azatoth commented Nov 29, 2025

To allow the use case where you want to screenshot to clipboard but
still want to have it stored to file as well for future reference.

Summary by CodeRabbit

  • New Features

    • Screenshot save now supports "Both (File and Clipboard)" — save to file and copy to clipboard in one action.
    • New "Hide recommended videos" option to hide the sidebar recommendations.
  • UI/Text updates

    • Various settings titles standardized to sentence case for consistent UI wording.
  • Removed/Changed

    • Playlist management toggle reworked into separate controls for remove and reset playlist actions (playlist management settings adjusted).

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 29, 2025

Caution

Review failed

Failed to post review comments

Walkthrough

Adds a new screenshot save option "both" (file + clipboard) across types, locales, settings UI, and screenshot implementation. Splits playlist management flag into separate remove/reset flags, introduces hide-sidebar-recommended-videos feature (CSS + runtime), updates message handlers and default configuration, and normalizes many locale title capitalizations.

Changes

Cohort / File(s) Summary
Localization (many locales)
public/locales/*.json, e.g. public/locales/en-US.json, public/locales/en-GB.json, public/locales/ca-ES.json, public/locales/*.json
Added screenshotButton.saveAs.both in en files; updated settings.optionDisabled.specificOption.screenshotButtonFileFormat to mention "Both"; removed enablePlaylistManagementButtons translations in many locales; normalized title casing (e.g., "Button placement settings", "On-screen display settings", "YouTube API V3 key").
Locale typings
public/locales/en-US.json.d.ts
Updated EnUS interface to include new screenshotButton.saveAs.both, added playlistManagement keys, renamed playlist management flags, and adjusted title casing in types.
Type definitions & messages
src/types/index.ts, src/utils/constants.ts
Added "both" to screenshotTypes / ScreenshotType; replaced enable_playlist_management_buttons with enable_playlist_remove_button and enable_playlist_reset_button; added enable_hide_sidebar_recommended_videos; added/send message mappings for hideSidebarRecommendedVideosChange, playlistRemoveButtonChange, playlistResetButtonChange; updated defaultConfiguration and schema.
Settings UI
src/components/Settings/Settings.tsx
Added "both" option to ScreenshotSaveAsOptions; removed single playlist-management toggle and added new flags/controls for playlist remove/reset and hide-sidebar toggle.
Screenshot feature
src/features/screenshotButton/index.ts
Refactored into helpers copyToClipboard and saveToFile; orchestrates operations based on `"clipboard"
Hide sidebar feature
src/features/hideSidebarRecommendedVideos/index.ts, src/features/hideSidebarRecommendedVideos/index.css
New feature module and CSS class .yte-hide-sidebar-recommended-videos with enable/disable functions; applies class when option enabled and target element exists.
Playlist management feature
src/features/playlistManagementButtons/index.ts, src/features/playlistManagementButtons/ActionButton/index.css
Reworked to use two granular flags (remove/reset), dark-mode aware icons, thumbnail-overlay checks, debounced MutationObserver, and updated styling for dark-mode hover.
Runtime wiring / pages
src/pages/content/index.ts, src/pages/embedded/index.ts, src/pages/embedded/index.ts
Added storage-change handlers and message cases for hideSidebarRecommendedVideosChange, playlistRemoveButtonChange, playlistResetButtonChange; integrated hide-sidebar enablement during initial setup; adjusted enable/disable flows for playlist buttons.
Other feature tweaks
src/features/hidePlaylistRecommendationsFromHomePage/index.ts, src/features/videoHistory/index.ts
Added runtime guard to run hide-playlist-recommendations only on home page; replaced direct badge query with waitForElement usage for official-artist detection.
Package
package.json
Bumped monaco-editor from ^0.54.0^0.55.1.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant User
participant SettingsUI as Settings UI
participant ContentScript as Screenshot Feature
participant ClipboardAPI as Clipboard API
participant Download as File Download
participant Tooltip as Tooltip UI

User->>SettingsUI: select "Both" for screenshot save-as
SettingsUI->>ContentScript: store option (both)
User->>ContentScript: trigger screenshot
ContentScript->>Tooltip: show "Saving…" tooltip
alt both includes clipboard
ContentScript->>ClipboardAPI: copy image/png (copyToClipboard)
ClipboardAPI-->>ContentScript: success / failure
end
alt both includes file
ContentScript->>Download: create blob URL & download file (saveToFile)
Download-->>ContentScript: started
end
ContentScript->>Tooltip: update tooltip (success/failure)
Tooltip-->>User: show result, cleanup after timeout

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Mixed changes across many areas: i18n, types, settings UI, feature implementations, runtime message handling, and CSS.
  • Areas to focus review on:
    • screenshotButton: concurrency and error handling when running clipboard + file operations together; tooltip lifecycle.
    • types/constants and message mappings: ensure message names and payload keys match consumers.
    • playlistManagementButtons: MutationObserver debounce correctness and DOM selectors (thumbnail overlay selector).
    • hideSidebarRecommendedVideos: waitForElement and class application/removal robustness across page states.

Possibly related PRs

Poem

🐰
I hop and I nibble on code so bright,
Now screenshots leap to clipboard and file in flight.
Two little helpers perform the trick,
Clipboard and disk — both done quick! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature addition: enabling simultaneous screenshot saving to both file and clipboard, which is the primary change across the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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 (3)
src/features/screenshotButton/index.ts (3)

29-54: Consider updating tooltip message when "both" is selected.

When screenshot_save_as is "both", the tooltip at line 37 displays "Screenshot copied to clipboard" but doesn't indicate that the file is also being saved. This could confuse users who expect confirmation that both operations are occurring.

Consider checking the screenshot_save_as value and displaying a more comprehensive message like "Screenshot copied to clipboard and saved to file" when "both" is selected.

Example approach:

const copyToClipboard = async () => {
	const screenshotButton = getFeatureButton("screenshotButton");
	if (!screenshotButton) return;
	const tooltipText = screenshot_save_as === "both" 
		? window.i18nextInstance.t("pages.content.features.screenshotButton.copiedToBoth")
		: window.i18nextInstance.t("pages.content.features.screenshotButton.copiedToClipboard");
	const { listener, remove } = createTooltip({
		direction: "up",
		element: screenshotButton,
		featureName: "screenshotButton",
		id: "yte-feature-screenshotButton-tooltip",
		text: tooltipText
	});
	// ... rest of function
};

Note: This would require adding the new translation key to the locale files.


56-65: Add error feedback for file save failures.

The saveToFile function silently returns early at line 59 if the blob creation fails, and the outer catch block at line 73 silently swallows any errors. When "both" is selected, users might see the "copied to clipboard" tooltip and assume the file was also saved successfully, even if it failed.

Consider adding user feedback (e.g., console error or tooltip) when file save operations fail, especially for the "both" mode where partial success could be confusing.

Example:

const saveToFile = async () => {
	try {
		const mimeType = `image/${screenshot_format}`;
		const blob = await new Promise<Nullable<Blob>>((resolve) => canvas.toBlob(resolve, mimeType));
		if (!blob) {
			console.error("Failed to create screenshot blob");
			return;
		}
		const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
		const a = document.createElement("a");
		a.href = URL.createObjectURL(blob);
		a.download = `Screenshot-${location.href.match(/[\?|\&]v=([^&]+)/)?.[1]}-${timestamp}.${screenshot_format}`;
		a.click();
	} catch (error) {
		console.error("Failed to save screenshot file:", error);
	}
};

67-72: Consider parallel execution for better performance.

The current implementation executes clipboard copy and file save sequentially with await (lines 67-72). For the "both" option, these operations could be executed in parallel using Promise.all() since they're independent.

This is a minor optimization and the current sequential approach is safer, so this is optional.

if (screenshot_save_as === "both") {
	await Promise.all([copyToClipboard(), saveToFile()]);
} else if (screenshot_save_as === "clipboard") {
	await copyToClipboard();
} else if (screenshot_save_as === "file") {
	await saveToFile();
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 57b89de and 7e18c45.

📒 Files selected for processing (6)
  • public/locales/en-GB.json (3 hunks)
  • public/locales/en-US.json (2 hunks)
  • public/locales/en-US.json.d.ts (2 hunks)
  • src/components/Settings/Settings.tsx (1 hunks)
  • src/features/screenshotButton/index.ts (1 hunks)
  • src/types/index.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/features/screenshotButton/index.ts (3)
src/features/buttonPlacement/utils.ts (1)
  • getFeatureButton (35-37)
src/utils/utilities.ts (1)
  • createTooltip (231-327)
src/types/index.ts (1)
  • Nullable (29-29)
🔇 Additional comments (6)
src/types/index.ts (1)

114-115: LGTM! Type definition correctly expanded.

The addition of "both" to the screenshotTypes constant properly extends the allowed values for ScreenshotType. This change maintains type safety throughout the codebase.

src/components/Settings/Settings.tsx (1)

267-271: LGTM! UI option correctly integrated.

The new "both" option is properly added to the ScreenshotSaveAsOptions array with appropriate translation key. The existing logic at line 174 correctly keeps the format selector enabled when "both" is selected, allowing users to configure the file format for the file save portion of the operation.

src/features/screenshotButton/index.ts (1)

41-41: Note: MIME type inconsistency between clipboard and file operations.

Clipboard copy always uses "image/png" (line 41) regardless of the user's configured screenshot_format, while file save uses the configured format (line 57). When "both" is selected, this means the clipboard and file will have different formats.

This is likely intentional due to browser clipboard API limitations with certain formats, but it might be worth documenting this behavior or ensuring the format selector description makes this clear to users.

Can you confirm this MIME type difference is intentional? If so, consider adding a comment explaining the constraint:

// Clipboard API has limited format support, always use PNG for reliability
const mimeType = "image/png";

Also applies to: 57-57

public/locales/en-US.json (1)

139-139: LGTM! Translations correctly added and updated.

The new "both" option label is clear and descriptive, and the updated description at line 139 correctly reflects that the format setting applies to both 'File' and 'Both' save types. These changes align well with the feature implementation.

Also applies to: 531-532

public/locales/en-US.json.d.ts (1)

81-81: LGTM! Type definitions correctly updated.

The TypeScript declarations properly reflect the changes made to the JSON locale file, maintaining type safety for the new "both" option and updated description string.

Also applies to: 410-410

public/locales/en-GB.json (1)

139-139: LGTM! British English translations consistent.

The en-GB locale changes match the en-US additions appropriately. The new "both" option and updated description are correctly translated, and existing British English conventions (like "colour") are properly maintained throughout the file.

Also applies to: 531-532

@VampireChicken12
Copy link
Copy Markdown
Member

@azatoth I appreciate your contribution but your changes should be made on the dev branch.

To allow the use case where you want to screenshot to clipboard but
still want to have it stored to file as well for future reference.
@azatoth azatoth force-pushed the add-screenshot-both-option branch from 7e18c45 to 8ba68d6 Compare November 29, 2025 19:24
@azatoth azatoth changed the base branch from main to dev November 29, 2025 19:25
@azatoth
Copy link
Copy Markdown
Contributor Author

azatoth commented Nov 29, 2025

@azatoth I appreciate your contribution but your changes should be made on the dev branch.

rebased onto dev

@VampireChicken12
Copy link
Copy Markdown
Member

VampireChicken12 commented Nov 29, 2025

@azatoth Never mind I didn't read the code right my bad

@VampireChicken12 VampireChicken12 merged commit bfcc8db into YouTube-Enhancer:dev Nov 29, 2025
1 check passed
@github-project-automation github-project-automation Bot moved this from Todo to Done - Released in YouTube Enhancer Nov 29, 2025
@github-actions
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.32.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done - Released

Development

Successfully merging this pull request may close these issues.

2 participants