Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5,491 changes: 5,491 additions & 0 deletions desktop/package-lock.json

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions desktop/src-tauri/src/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -597,3 +597,30 @@ pub fn get_cargo_features() -> Vec<String> {

enabled_features
}

#[tauri::command]
pub async fn read_translation_file(language: String, namespace: String) -> Result<String> {
let exe_path = std::env::current_exe()?;
tracing::debug!("Executable path: {:?}", exe_path);

let resource_dir = exe_path
.parent() // Contents/MacOS
.and_then(|p| p.parent()) // Contents
.ok_or_else(|| eyre!("Could not find Contents directory"))?
.join("Resources")
.join("locales")
.join(language)
.join(format!("{}.json", namespace));

tracing::debug!("Looking for translation file at: {:?}", resource_dir);

if !resource_dir.exists() {
tracing::error!("Translation file not found: {:?}", resource_dir);
return Err(eyre!("Translation file not found: {:?}", resource_dir));
}

tracing::debug!("Reading translation file: {:?}", resource_dir);
let content = std::fs::read_to_string(&resource_dir)?;
tracing::debug!("Successfully read {} bytes", content.len());
Ok(content)
}
1 change: 1 addition & 0 deletions desktop/src-tauri/src/cmd/ytdlp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub async fn download_audio(app_handle: AppHandle, url: String, out_path: String
let mut cmd = std::process::Command::new(path);
let cmd = cmd
.args([
"--no-warnings",
"--progress-template",
"{\"progress\": \"%(progress.percent)s\", \"total_bytes\": \"%(progress.total_bytes)s\", \"progress_str\": \"%(progress._percent_str)s\"}\n",
"--no-playlist",
Expand Down
3 changes: 3 additions & 0 deletions desktop/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ mod screen_capture_kit;

use eyre::{eyre, Result};
use tauri_plugin_window_state::StateFlags;
use std::fs;
use std::path::PathBuf;

use utils::LogError;

Expand Down Expand Up @@ -96,6 +98,7 @@ fn main() -> Result<()> {
cmd::ytdlp::get_temp_path,
cmd::is_crashed_recently,
cmd::rename_crash_file,
cmd::read_translation_file,
#[cfg(windows)]
cmd::set_high_gpu_preference
])
Expand Down
15 changes: 7 additions & 8 deletions desktop/src-tauri/tauri.macos.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
"macOS": {
"entitlements": "entitlements.plist",
"frameworks": [
"ffmpeg/lib/libavcodec.60.dylib",
"ffmpeg/lib/libavdevice.60.dylib",
"ffmpeg/lib/libavfilter.9.dylib",
"ffmpeg/lib/libavformat.60.dylib",
"ffmpeg/lib/libavutil.58.dylib",
"ffmpeg/lib/libffmpeg.6.dylib",
"ffmpeg/lib/libswresample.4.dylib",
"ffmpeg/lib/libswscale.7.dylib"
"ffmpeg/lib/libavcodec.62.dylib",
"ffmpeg/lib/libavdevice.62.dylib",
"ffmpeg/lib/libavfilter.11.dylib",
"ffmpeg/lib/libavformat.62.dylib",
"ffmpeg/lib/libavutil.60.dylib",
"ffmpeg/lib/libswresample.6.dylib",
"ffmpeg/lib/libswscale.9.dylib"
],
"signingIdentity": "-",
"hardenedRuntime": false,
Expand Down
8 changes: 4 additions & 4 deletions desktop/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,19 @@ export const llmDefaultMaxTokens = 8192 // https://docs.anthropic.com/en/docs/ab
export const llmLimitsUrl = 'https://console.anthropic.com/settings/limits'
export const llmCostUrl = 'https://console.anthropic.com/settings/cost'

export const ytDlpVersion = '2025.01.150'
export const ytDlpVersion = '2025.10.22'
export const ytDlpConfig = {
windows: {
url: 'https://github.com/yt-dlp/yt-dlp/releases/download/2025.01.15/yt-dlp.exe', // signed with self certificate. better than nothing
url: 'https://github.com/yt-dlp/yt-dlp/releases/download/2025.10.22/yt-dlp.exe', // signed with self certificate. better than nothing
name: 'yt-dlp.exe',
},
linux: {
url: 'https://github.com/yt-dlp/yt-dlp/releases/download/2025.01.15/yt-dlp_linux',
url: 'https://github.com/yt-dlp/yt-dlp/releases/download/2025.10.22/yt-dlp_linux',
name: 'yt-dlp_linux',
},
macos: {
// Universal binary
url: 'https://github.com/yt-dlp/yt-dlp/releases/download/2025.01.15/yt-dlp_macos',
url: 'https://github.com/yt-dlp/yt-dlp/releases/download/2025.10.22/yt-dlp_macos',
name: 'yt-dlp_macos',
},
}
Expand Down
43 changes: 27 additions & 16 deletions desktop/src/lib/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { resolveResource } from '@tauri-apps/api/path'
import * as fs from '@tauri-apps/plugin-fs'
import { invoke } from '@tauri-apps/api/core'
import { locale } from '@tauri-apps/plugin-os'
import i18n, { LanguageDetectorAsyncModule } from 'i18next'
import resourcesToBackend from 'i18next-resources-to-backend'
Expand Down Expand Up @@ -40,11 +39,15 @@ const LanguageDetector: LanguageDetectorAsyncModule = {
async: true, // If this is set to true, your detect function receives a callback function that you should call with your language, useful to retrieve your language stored in AsyncStorage for example
detect: (callback) => {
locale().then((detectedLocale) => {
console.log('Detected system locale:', detectedLocale)
const prefs_language = localStorage.getItem('prefs_display_language')
console.log('Stored language preference:', prefs_language)
if (prefs_language) {
const locale = JSON.parse(prefs_language)
console.log('Using stored preference:', locale)
callback(locale)
} else {
console.log('Using detected locale:', detectedLocale)
if (detectedLocale) {
callback(detectedLocale)
}
Expand All @@ -60,20 +63,28 @@ i18n.use(LanguageDetector)
if (!supportedLanguageKeys.includes(language)) {
return
}
const resourcePath = `./locales/${language}`
const languageDirectory = await resolveResource(resourcePath)
const files = await fs.readDir(languageDirectory)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const translations: any = {}
await Promise.all(
files.map(async (file) => {
const filePath = `${languageDirectory}/${file.name}`
const namespace = file.name.replace('.json', '')
const content = await fs.readTextFile(filePath)
translations[namespace] = JSON.parse(content)
})
)
return translations
try {
// Use invoke to read translation files from Rust side
const translations: any = {}

// Read common.json and language.json
const namespaces = ['common', 'language']
await Promise.all(
namespaces.map(async (namespace) => {
try {
const content = await invoke('read_translation_file', { language, namespace })
translations[namespace] = JSON.parse(content as string)
} catch (error) {
console.warn(`Failed to load ${namespace} translations:`, error)
}
})
)

return translations
} catch (error) {
console.error('i18n resource loading failed:', error)
return {}
}
})
)
.init({
Expand Down
3 changes: 3 additions & 0 deletions desktop/src/lib/ytdlp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export async function downloadYtDlp() {
}

export async function downloadAudio(url: string, inDocuments?: boolean) {
if (!(await exists())) {
await downloadYtDlp()
}
const outPath = await invoke<string>('get_temp_path', { ext: 'm4a', inDocuments })
await invoke<string>('download_audio', { url, outPath })
return outPath
Expand Down