Skip to content

feat: language preference persistence per channel#26

Merged
STRRL merged 2 commits intomasterfrom
STRRL/drag-drop-srt
Jan 1, 2026
Merged

feat: language preference persistence per channel#26
STRRL merged 2 commits intomasterfrom
STRRL/drag-drop-srt

Conversation

@STRRL
Copy link
Owner

@STRRL STRRL commented Jan 1, 2026

Summary

Implements automatic language preference persistence for each channel. When a user selects a language for a video from a specific channel, the app remembers and auto-applies that preference to future videos from the same channel.

Implementation

  • Extended Settings struct with ChannelLanguagePrefs map
  • Added GetChannelLanguagePreference() and SetChannelLanguagePreference() backend methods
  • Modified StartTranscription() to save preferences automatically
  • Updated NewTranscriptionPage to query and auto-select saved language preferences

Behavior

  • New channels default to global SourceLang setting
  • Preferences stored as {platform}:{channelID} with fallback to channel name
  • Settings persisted to ~/.config/TransCube/settings.json
  • Backward compatible with existing settings files

🤖 Generated with Claude Code

When a user selects a language for a video from a specific channel, the app now remembers and automatically applies that preference when processing future videos from the same channel. Preferences are stored per platform and channel identifier (with fallback to channel name), persisted to settings.json, and gracefully handle backward compatibility with existing settings files.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@mesa-dot-dev
Copy link

mesa-dot-dev bot commented Jan 1, 2026

Mesa Description

TL;DR

Implements automatic language preference persistence for each channel. When a user selects a language for a video from a specific channel, the app remembers and auto-applies that preference to future videos from the same channel.

What changed?

  • Extended Settings struct with ChannelLanguagePrefs map
  • Added GetChannelLanguagePreference() and SetChannelLanguagePreference() backend methods
  • Modified StartTranscription() to save preferences automatically
  • Updated NewTranscriptionPage to query and auto-select saved language preferences
  • New channels default to global SourceLang setting
  • Preferences stored as {platform}:{channelID} with fallback to channel name
  • Settings persisted to ~/.config/TransCube/settings.json
  • Backward compatible with existing settings files

Description generated by Mesa. Update settings

Copy link

@mesa-dot-dev mesa-dot-dev bot left a comment

Choose a reason for hiding this comment

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

Performed full review of b9beb81...076eb7b

Analysis

  1. Unbounded Storage Growth: The map-based storage for channel language preferences has no eviction policy, potentially causing unlimited growth for users who watch many channels.

  2. Frontend Race Condition: Platform detection happens asynchronously, but preference lookup occurs immediately when metadata loads, which could lead to using 'unknown' as the platform identifier.

  3. No User Interface for Management: Users cannot view or clear their saved channel preferences through any UI, limiting control over accumulated preferences.

  4. Preference Saving Before Validation: Language preferences are saved in StartTranscription() before the transcription task begins, meaning preferences will be persisted even for failed transcriptions.

Tip

Help

Slash Commands:

  • /review - Request a full code review
  • /review latest - Review only changes since the last review
  • /describe - Generate PR description. This will update the PR body or issue comment depending on your configuration
  • /help - Get help with Mesa commands and configuration options

0 files reviewed | 2 comments | Edit Agent SettingsRead Docs

setVideoMetadata(metadata)
if (metadata.isValid && metadata.channel) {
try {
const preferredLang = await GetChannelLanguagePreference(
Copy link

Choose a reason for hiding this comment

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

Medium

The platform variable may still be 'unknown' when this executes. Platform detection runs asynchronously via DetectPlatform(url), but there's no guarantee it completes before handleMetadataLoaded is called. If metadata loads first, the preference lookup will use 'unknown' as the platform key, likely returning no saved preference. Consider adding a check like if (platform === 'unknown') return or ensuring platform detection completes before querying preferences.

Agent: ⚛️ React • Fix in Cursor • Fix in Claude

Prompt for Agent
Task: Address review feedback left on GitHub.
Repository: STRRL/transcube-webapp#26
File: frontend/src/pages/NewTranscriptionPage.tsx#L189
Action: Open this file location in your editor, inspect the highlighted code, and resolve the issue described below.

Feedback:
The `platform` variable may still be `'unknown'` when this executes. Platform detection runs asynchronously via `DetectPlatform(url)`, but there's no guarantee it completes before `handleMetadataLoaded` is called. If metadata loads first, the preference lookup will use `'unknown'` as the platform key, likely returning no saved preference. Consider adding a check like `if (platform === 'unknown') return` or ensuring platform detection completes before querying preferences.

metadata.channel
)
if (preferredLang) {
setSourceLang(preferredLang)
Copy link

Choose a reason for hiding this comment

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

Medium

Race condition: If the user manually selects a different source language while GetChannelLanguagePreference is still pending, the delayed setSourceLang(preferredLang) will overwrite the user's manual selection. Consider tracking whether the user has made a manual selection (e.g., via a ref or flag) and skip the auto-selection if they have, or use an AbortController to cancel the pending update.

Agent: ⚛️ React • Fix in Cursor • Fix in Claude

Prompt for Agent
Task: Address review feedback left on GitHub.
Repository: STRRL/transcube-webapp#26
File: frontend/src/pages/NewTranscriptionPage.tsx#L195
Action: Open this file location in your editor, inspect the highlighted code, and resolve the issue described below.

Feedback:
Race condition: If the user manually selects a different source language while `GetChannelLanguagePreference` is still pending, the delayed `setSourceLang(preferredLang)` will overwrite the user's manual selection. Consider tracking whether the user has made a manual selection (e.g., via a ref or flag) and skip the auto-selection if they have, or use an AbortController to cancel the pending update.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 185 to 189
const handleMetadataLoaded = async (metadata: VideoMetadata) => {
setVideoMetadata(metadata)
if (metadata.isValid && metadata.channel) {
try {
const preferredLang = await GetChannelLanguagePreference(

Choose a reason for hiding this comment

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

P1 Badge Memoize metadata handler to avoid endless metadata refetches

VideoPreview’s useEffect depends on the onMetadataLoaded prop, so when this page now passes an inline handleMetadataLoaded function that is recreated every render, the effect reruns on every render even when the URL is unchanged (see VideoPreview.tsx where the effect depends on onMetadataLoaded). Each rerender schedules another ParseVideoUrl call and preference lookup every ~500 ms, producing continuous metadata fetches and state churn once the first metadata load updates state. The handler should be memoized (e.g., useCallback) or the dependency removed to prevent repeated backend calls.

Useful? React with 👍 / 👎.

The handleMetadataLoaded callback was causing VideoPreview's useEffect to re-run on every render because it was creating a new function reference each time. Wrapped with useCallback and proper dependencies to stabilize the reference.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@STRRL STRRL merged commit c44db12 into master Jan 1, 2026
1 check passed
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.

1 participant