← back to dennisrongo__cut-clean

Function bodies 405 total

All specs Real LLM only Function bodies
detect_filler_words function · rust · L167-L228 (62 LOC)
src-tauri/src/services/filler_detector.rs
pub fn detect_filler_words(
    transcription: &Transcription,
    config: &FillerDetectionConfig,
) -> Vec<FillerWordDetection> {
    let mut detections = Vec::new();

    // Build phonetic map for faster lookup
    let phonetic_map: HashMap<String, Vec<&str>> = build_phonetic_map();

    for word in &transcription.words {
        let word_lower = word.word.to_lowercase();
        let word_clean = word_clean(&word_lower);

        // Skip very short words
        if word_clean.len() < 2 {
            continue;
        }

        // Check direct matches
        if let Some(filler_type) = find_direct_match(&word_clean) {
            if word.confidence >= config.min_confidence {
                detections.push(FillerWordDetection {
                    start: word.start,
                    end: word.end,
                    word: filler_type.as_str().to_string(),
                    confidence: calculate_filler_confidence(&word, &filler_type, &word_clean),
                    filler_type
build_phonetic_map function · rust · L233-L242 (10 LOC)
src-tauri/src/services/filler_detector.rs
fn build_phonetic_map() -> HashMap<String, Vec<&'static str>> {
    let mut map = HashMap::new();

    for (filler, _) in FILLER_WORDS {
        let encoded = phonetic_encode(filler);
        map.entry(encoded).or_insert_with(Vec::new).push(*filler);
    }

    map
}
find_direct_match function · rust · L247-L253 (7 LOC)
src-tauri/src/services/filler_detector.rs
fn find_direct_match(word: &str) -> Option<FillerType> {
    FILLER_WORDS
        .iter()
        .find(|(filler, _)| *filler == word)
        .map(|(_, filler_type)| filler_type.clone())
        .or_else(|| get_additional_filler(word))
}
find_filler_type function · rust · L258-L261 (4 LOC)
src-tauri/src/services/filler_detector.rs
fn find_filler_type(word: &str) -> FillerType {
    find_direct_match(word)
        .unwrap_or_else(|| FillerType::Other(word.to_string()))
}
word_clean function · rust · L266-L270 (5 LOC)
src-tauri/src/services/filler_detector.rs
fn word_clean(word: &str) -> String {
    word.chars()
        .filter(|c| c.is_alphabetic() || c.is_whitespace())
        .collect()
}
calculate_filler_confidence function · rust · L280-L301 (22 LOC)
src-tauri/src/services/filler_detector.rs
fn calculate_filler_confidence(word: &TimedWord, filler_type: &FillerType, matched: &str) -> f64 {
    let base_confidence = word.confidence;

    // Boost for exact matches
    let match_bonus = if filler_type.as_str() == matched {
        0.2
    } else {
        0.0
    };

    // Adjust based on word duration (filler words are typically short)
    let duration = word.end - word.start;
    let duration_factor = if duration < 0.5 {
        1.0
    } else if duration < 1.0 {
        0.9
    } else {
        0.7
    };

    (base_confidence + match_bonus).min(1.0) * duration_factor
}
calculate_similarity function · rust · L306-L321 (16 LOC)
src-tauri/src/services/filler_detector.rs
fn calculate_similarity(a: &str, b: &str) -> f64 {
    let a_len = a.chars().count();
    let b_len = b.chars().count();

    if a_len == 0 && b_len == 0 {
        return 1.0;
    }
    if a_len == 0 || b_len == 0 {
        return 0.0;
    }

    let distance = levenshtein_distance(a, b);
    let max_len = a_len.max(b_len);

    1.0 - (distance as f64 / max_len as f64)
}
Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
levenshtein_distance function · rust · L326-L363 (38 LOC)
src-tauri/src/services/filler_detector.rs
fn levenshtein_distance(a: &str, b: &str) -> usize {
    let a_chars: Vec<char> = a.chars().collect();
    let b_chars: Vec<char> = b.chars().collect();
    let a_len = a_chars.len();
    let b_len = b_chars.len();

    let mut matrix = vec![vec![0; b_len + 1]; a_len + 1];

    // Initialize first row and column
    for i in 0..=a_len {
        matrix[i][0] = i;
    }
    for j in 0..=b_len {
        matrix[0][j] = j;
    }

    // Fill matrix
    for i in 1..=a_len {
        for j in 1..=b_len {
            let cost = if a_chars[i - 1] == b_chars[j - 1] {
                0
            } else {
                1
            };

            matrix[i][j] = [
                matrix[i - 1][j] + 1,      // deletion
                matrix[i][j - 1] + 1,      // insertion
                matrix[i - 1][j - 1] + cost, // substitution
            ]
            .into_iter()
            .min()
            .unwrap();
        }
    }

    matrix[a_len][b_len]
}
merge_overlapping_detections function · rust · L368-L392 (25 LOC)
src-tauri/src/services/filler_detector.rs
fn merge_overlapping_detections(mut detections: Vec<FillerWordDetection>) -> Vec<FillerWordDetection> {
    if detections.is_empty() {
        return detections;
    }

    // Sort by start time
    detections.sort_by(|a, b| a.start.partial_cmp(&b.start).unwrap());

    let mut merged = Vec::new();
    let mut current = detections[0].clone();

    for detection in detections.into_iter().skip(1) {
        if detection.start <= current.end + 0.2 {
            // Overlapping or close - merge
            current.end = current.end.max(detection.end);
            current.confidence = current.confidence.max(detection.confidence);
        } else {
            merged.push(current);
            current = detection;
        }
    }
    merged.push(current);

    merged
}
create_mock_transcription function · rust · L403-L484 (82 LOC)
src-tauri/src/services/filler_detector.rs
pub fn create_mock_transcription(duration: f64) -> Transcription {
    let words = vec![
        TimedWord {
            word: "Hello".into(),
            start: 0.0,
            end: 0.5,
            confidence: 0.98,
        },
        TimedWord {
            word: "um".into(),
            start: 0.7,
            end: 0.9,
            confidence: 0.92,
        },
        TimedWord {
            word: "today".into(),
            start: 1.0,
            end: 1.3,
            confidence: 0.95,
        },
        TimedWord {
            word: "we're".into(),
            start: 1.4,
            end: 1.7,
            confidence: 0.97,
        },
        TimedWord {
            word: "going".into(),
            start: 1.8,
            end: 2.1,
            confidence: 0.96,
        },
        TimedWord {
            word: "to".into(),
            start: 2.2,
            end: 2.4,
            confidence: 0.99,
        },
        TimedWord {
            word: "uh".into(),
            start: 2
detect_fillers_from_audio function · rust · L494-L527 (34 LOC)
src-tauri/src/services/filler_detector.rs
pub fn detect_fillers_from_audio(
    _audio_path: &str,
    _config: &FillerDetectionConfig,
) -> Result<Vec<FillerWordDetection>, String> {
    // Placeholder: Return mock detections
    // In production, this would:
    // 1. Transcribe audio using Whisper
    // 2. Run filler detection on transcription
    // 3. Return results

    Ok(vec![
        FillerWordDetection {
            start: 2.0,
            end: 2.5,
            word: "um".into(),
            confidence: 0.92,
            filler_type: FillerType::Um,
        },
        FillerWordDetection {
            start: 8.0,
            end: 8.4,
            word: "uh".into(),
            confidence: 0.88,
            filler_type: FillerType::Uh,
        },
        FillerWordDetection {
            start: 15.0,
            end: 15.5,
            word: "like".into(),
            confidence: 0.85,
            filler_type: FillerType::Like,
        },
    ])
}
test_phonetic_encoding function · rust · L534-L544 (11 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_phonetic_encoding() {
        // First character is kept, then consonants only
        let encoded = phonetic_encode("um");
        assert_eq!(encoded, "um00"); // 'u' is first (vowel kept), 'm' is consonant

        let encoded = phonetic_encode("uh");
        assert_eq!(encoded.len(), 4); // Normalized to 4 chars

        let encoded = phonetic_encode("like");
        assert_eq!(encoded.len(), 4);
    }
test_levenshtein_distance function · rust · L547-L551 (5 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_levenshtein_distance() {
        assert_eq!(levenshtein_distance("um", "um"), 0);
        assert_eq!(levenshtein_distance("um", "uh"), 1);
        assert_eq!(levenshtein_distance("hello", "hallo"), 1);
    }
test_similarity_calculation function · rust · L554-L560 (7 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_similarity_calculation() {
        let sim = calculate_similarity("um", "um");
        assert_eq!(sim, 1.0);

        let sim = calculate_similarity("um", "uh");
        assert!(sim > 0.0 && sim < 1.0);
    }
test_filler_detection function · rust · L563-L577 (15 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_filler_detection() {
        let transcription = create_mock_transcription(5.0);
        let config = FillerDetectionConfig::default();

        let detections = detect_filler_words(&transcription, &config);

        assert!(!detections.is_empty());

        // Check that "um" and "uh" are detected
        let has_um = detections.iter().any(|d| d.word == "um");
        let has_uh = detections.iter().any(|d| d.word == "uh");

        assert!(has_um, "Should detect 'um'");
        assert!(has_uh, "Should detect 'uh'");
    }
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
test_direct_match_all_filler_types function · rust · L580-L591 (12 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_direct_match_all_filler_types() {
        // Test direct matching for all filler types
        assert!(find_direct_match("um").is_some());
        assert!(find_direct_match("uh").is_some());
        assert!(find_direct_match("er").is_some());
        assert!(find_direct_match("like").is_some());
        assert!(find_direct_match("you know").is_some());
        assert!(find_direct_match("y'know").is_some());
        assert!(find_direct_match("I mean").is_some());
        assert!(find_direct_match("actually").is_some());
        assert!(find_direct_match("basically").is_some());
    }
test_phonetic_variations function · rust · L594-L607 (14 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_phonetic_variations() {
        // Test phonetic encoding for common filler variations
        let um_variants = vec!["um", "umm", "uum"];
        for variant in um_variants {
            let encoded = phonetic_encode(variant);
            assert!(!encoded.is_empty());
        }

        let uh_variants = vec!["uh", "uhh", "uuh"];
        for variant in uh_variants {
            let encoded = phonetic_encode(variant);
            assert!(!encoded.is_empty());
        }
    }
test_levenshtein_distance_edge_cases function · rust · L610-L622 (13 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_levenshtein_distance_edge_cases() {
        // Empty strings
        assert_eq!(levenshtein_distance("", ""), 0);
        assert_eq!(levenshtein_distance("", "test"), 4);
        assert_eq!(levenshtein_distance("test", ""), 4);

        // Single character
        assert_eq!(levenshtein_distance("a", "a"), 0);
        assert_eq!(levenshtein_distance("a", "b"), 1);

        // Unicode handling (should work with char count)
        assert_eq!(levenshtein_distance("café", "cafe"), 1);
    }
test_similarity_thresholds function · rust · L625-L637 (13 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_similarity_thresholds() {
        // Test similarity calculation at various thresholds
        let exact_match = calculate_similarity("um", "um");
        assert_eq!(exact_match, 1.0);

        let one_char_diff = calculate_similarity("um", "uh");
        // "um" and "uh" have 1 character difference out of 2
        // Similarity = 1 - (1/2) = 0.5
        assert!(one_char_diff >= 0.0 && one_char_diff <= 1.0);

        let completely_different = calculate_similarity("um", "like");
        assert!(completely_different < 0.5);
    }
test_confidence_calculation_with_duration function · rust · L640-L654 (15 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_confidence_calculation_with_duration() {
        let word = TimedWord {
            word: "um".to_string(),
            start: 0.0,
            end: 0.3,  // Short duration
            confidence: 0.9,
        };

        let filler_type = FillerType::Um;
        let calculated_confidence = calculate_filler_confidence(&word, &filler_type, "um");

        // Short duration = higher confidence
        assert!(calculated_confidence > 0.8);
        assert!(calculated_confidence <= 1.0);
    }
test_confidence_calculation_long_duration function · rust · L657-L670 (14 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_confidence_calculation_long_duration() {
        let word = TimedWord {
            word: "um".to_string(),
            start: 0.0,
            end: 1.5,  // Long duration for "um"
            confidence: 0.9,
        };

        let filler_type = FillerType::Um;
        let calculated_confidence = calculate_filler_confidence(&word, &filler_type, "um");

        // Long duration = lower confidence factor
        assert!(calculated_confidence < 0.9);
    }
test_overlapping_detection_merging function · rust · L673-L697 (25 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_overlapping_detection_merging() {
        let detections = vec![
            FillerWordDetection {
                start: 1.0,
                end: 1.5,
                word: "um".to_string(),
                confidence: 0.9,
                filler_type: FillerType::Um,
            },
            FillerWordDetection {
                start: 1.4,  // Overlapping (within 0.2s)
                end: 2.0,
                word: "uh".to_string(),
                confidence: 0.85,
                filler_type: FillerType::Uh,
            },
        ];

        let merged = merge_overlapping_detections(detections);

        // Should merge into one detection
        assert_eq!(merged.len(), 1);
        assert_eq!(merged[0].start, 1.0);
        assert_eq!(merged[0].end, 2.0);
    }
test_non_overlapping_detections function · rust · L700-L722 (23 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_non_overlapping_detections() {
        let detections = vec![
            FillerWordDetection {
                start: 1.0,
                end: 1.5,
                word: "um".to_string(),
                confidence: 0.9,
                filler_type: FillerType::Um,
            },
            FillerWordDetection {
                start: 3.0,  // Not overlapping (> 0.2s gap)
                end: 3.5,
                word: "uh".to_string(),
                confidence: 0.85,
                filler_type: FillerType::Uh,
            },
        ];

        let merged = merge_overlapping_detections(detections);

        // Should NOT merge
        assert_eq!(merged.len(), 2);
    }
Want this analysis on your repo? https://repobility.com/scan/
test_merge_empty_detections function · rust · L725-L729 (5 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_merge_empty_detections() {
        let detections: Vec<FillerWordDetection> = vec![];
        let merged = merge_overlapping_detections(detections);
        assert_eq!(merged.len(), 0);
    }
test_filler_type_as_str function · rust · L732-L739 (8 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_filler_type_as_str() {
        assert_eq!(FillerType::Um.as_str(), "um");
        assert_eq!(FillerType::Uh.as_str(), "uh");
        assert_eq!(FillerType::Like.as_str(), "like");
        assert_eq!(FillerType::YouKnow.as_str(), "you know");
        assert_eq!(FillerType::IMean.as_str(), "I mean");
        assert_eq!(FillerType::Other("custom".to_string()).as_str(), "custom");
    }
test_word_clean function · rust · L742-L747 (6 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_word_clean() {
        assert_eq!(word_clean("um,"), "um");
        assert_eq!(word_clean("uh!"), "uh");
        assert_eq!(word_clean("like."), "like");
        assert_eq!(word_clean("you?"), "you");
    }
test_config_default function · rust · L750-L755 (6 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_config_default() {
        let config = FillerDetectionConfig::default();
        assert_eq!(config.min_confidence, 0.5);
        assert!(config.use_phonetic);
        assert!(config.custom_fillers.is_empty());
    }
test_find_filler_type function · rust · L758-L765 (8 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_find_filler_type() {
        assert!(matches!(find_filler_type("um"), FillerType::Um));
        assert!(matches!(find_filler_type("uh"), FillerType::Uh));
        assert!(matches!(find_filler_type("like"), FillerType::Like));
        assert!(matches!(find_filler_type("you know"), FillerType::YouKnow));
        assert!(matches!(find_filler_type("I mean"), FillerType::IMean));
        assert!(matches!(find_filler_type("custom"), FillerType::Other(_)));
    }
test_phonetic_encoding_normalization function · rust · L768-L775 (8 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_phonetic_encoding_normalization() {
        // Test that phonetic encoding normalizes to 4 characters
        let short = phonetic_encode("a");
        assert_eq!(short.len(), 4);

        let long = phonetic_encode("verylongword");
        assert_eq!(long.len(), 4);
    }
test_phonetic_encoding_vowel_removal function · rust · L778-L786 (9 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_phonetic_encoding_vowel_removal() {
        // Vowels after first character should be removed
        let encoded = phonetic_encode("audio");
        assert_eq!(encoded.len(), 4); // Normalized to 4 chars

        // First character is always kept
        let encoded = phonetic_encode("eaio");
        assert_eq!(encoded.chars().next(), Some('e'));
    }
test_timed_word_structure function · rust · L789-L802 (14 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_timed_word_structure() {
        let word = TimedWord {
            word: "test".to_string(),
            start: 1.0,
            end: 1.5,
            confidence: 0.95,
        };

        assert_eq!(word.word, "test");
        assert_eq!(word.start, 1.0);
        assert_eq!(word.end, 1.5);
        assert_eq!(word.confidence, 0.95);
        assert!(word.end > word.start);
    }
Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
test_transcription_structure function · rust · L805-L815 (11 LOC)
src-tauri/src/services/filler_detector.rs
    fn test_transcription_structure() {
        let transcription = Transcription {
            text: "test".to_string(),
            words: vec![],
            language: "en".to_string(),
        };

        assert_eq!(transcription.text, "test");
        assert_eq!(transcription.language, "en");
        assert!(transcription.words.is_empty());
    }
get_available_models function · rust · L42-L65 (24 LOC)
src-tauri/src/services/model_manager.rs
pub fn get_available_models() -> Vec<ModelInfo> {
    let active_model = get_active_model();
    let models = vec![
        WhisperModel::Tiny,
        WhisperModel::Base,
        WhisperModel::Small,
        WhisperModel::Medium,
        WhisperModel::Large,
    ];

    models
        .into_iter()
        .map(|model| {
            let is_downloaded = is_model_downloaded_impl(&model);
            ModelInfo {
                name: model.model_name().to_string(),
                display_name: model.display_name().to_string(),
                size_bytes: model.size_bytes(),
                is_downloaded,
                is_active: model == active_model,
            }
        })
        .collect()
}
is_model_downloaded_impl function · rust · L68-L73 (6 LOC)
src-tauri/src/services/model_manager.rs
fn is_model_downloaded_impl(model: &WhisperModel) -> bool {
    match get_model_path(*model) {
        Ok(path) => path.exists(),
        Err(_) => false,
    }
}
is_model_downloaded function · rust · L76-L81 (6 LOC)
src-tauri/src/services/model_manager.rs
pub fn is_model_downloaded(model_name: &str) -> Result<bool, String> {
    let model = WhisperModel::from_str(model_name)
        .ok_or_else(|| format!("Invalid model name: {}", model_name))?;

    Ok(is_model_downloaded_impl(&model))
}
get_active_model function · rust · L84-L98 (15 LOC)
src-tauri/src/services/model_manager.rs
pub fn get_active_model() -> WhisperModel {
    // Try to read from settings file
    if let Ok(models_dir) = get_models_dir() {
        let settings_path = models_dir.join(ACTIVE_MODEL_FILE);

        if let Ok(content) = fs::read_to_string(&settings_path) {
            if let Some(model) = WhisperModel::from_str(content.trim()) {
                return model;
            }
        }
    }

    // Default to Small model
    WhisperModel::Small
}
set_active_model function · rust · L101-L112 (12 LOC)
src-tauri/src/services/model_manager.rs
pub fn set_active_model(model_name: &str) -> Result<(), String> {
    let model = WhisperModel::from_str(model_name)
        .ok_or_else(|| format!("Invalid model name: {}", model_name))?;

    let models_dir = get_models_dir()?;
    let settings_path = models_dir.join(ACTIVE_MODEL_FILE);

    fs::write(&settings_path, model.model_name())
        .map_err(|e| format!("Failed to write model settings: {}", e))?;

    Ok(())
}
delete_model function · rust · L115-L135 (21 LOC)
src-tauri/src/services/model_manager.rs
pub fn delete_model(model_name: &str) -> Result<(), String> {
    let model = WhisperModel::from_str(model_name)
        .ok_or_else(|| format!("Invalid model name: {}", model_name))?;

    // Don't allow deleting the active model
    let active = get_active_model();
    if model == active {
        return Err("Cannot delete the active model. Please switch to a different model first.".to_string());
    }

    let model_path = get_model_path(model)?;

    if !model_path.exists() {
        return Err(format!("Model not found: {}", model_name));
    }

    fs::remove_file(&model_path)
        .map_err(|e| format!("Failed to delete model: {}", e))?;

    Ok(())
}
download_model_async function · rust · L141-L481 (341 LOC)
src-tauri/src/services/model_manager.rs
pub async fn download_model_async(
    model_name: String,
    app: tauri::AppHandle,
) -> Result<(), String> {
    println!("[MODEL DOWNLOAD] Starting download for model: {}", model_name);

    let model = WhisperModel::from_str(&model_name)
        .ok_or_else(|| format!("Invalid model name: {}", model_name))?;

    let model_path = get_model_path(model)?;
    let expected_size = model.size_bytes();
    println!("[MODEL DOWNLOAD] Model path: {:?}", model_path);
    println!("[MODEL DOWNLOAD] Expected size: {} bytes", expected_size);

    // Check if already downloaded
    if model_path.exists() {
        println!("[MODEL DOWNLOAD] Model already exists at path");
        return Err("Model already downloaded".to_string());
    }

    // Ensure models directory exists
    let models_dir = get_models_dir()?;
    println!("[MODEL DOWNLOAD] Models directory: {:?}", models_dir);
    let _ = std::fs::create_dir_all(&models_dir)
        .map_err(|e| format!("Failed to create models directory:
Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
verify_model_file function · rust · L242-L267 (26 LOC)
src-tauri/src/services/model_manager.rs
fn verify_model_file(path: &Path, expected_size: u64) -> Result<(), String> {
    // Check file exists
    if !path.exists() {
        return Err("Downloaded file not found".to_string());
    }

    // Check file size
    let metadata = std::fs::metadata(path)
        .map_err(|e| format!("Failed to read file metadata: {}", e))?;

    let actual_size = metadata.len();

    // Allow 5% variance in file size (actual HuggingFace sizes may vary)
    let size_variance = (expected_size as f64 * 0.05) as u64;
    let min_size = expected_size.saturating_sub(size_variance);
    let max_size = expected_size.saturating_add(size_variance);

    if actual_size < min_size || actual_size > max_size {
        return Err(format!(
            "File size mismatch: expected ~{} bytes, got {} bytes",
            expected_size, actual_size
        ));
    }

    Ok(())
}
new function · rust · L319-L326 (8 LOC)
src-tauri/src/services/model_manager.rs
    fn new(model_name: String, total_bytes: u64) -> Self {
        Self {
            last_emitted_percent: 0,
            last_emit_time: std::time::Instant::now(),
            model_name,
            total_bytes,
        }
    }
should_emit function · rust · L329-L354 (26 LOC)
src-tauri/src/services/model_manager.rs
    fn should_emit(&mut self, downloaded_bytes: u64) -> Option<ModelDownloadProgress> {
        let percent = if self.total_bytes > 0 {
            ((downloaded_bytes as f64 / self.total_bytes as f64) * 100.0) as u8
        } else {
            0
        };

        let percent_change = percent.abs_diff(self.last_emitted_percent);
        let time_elapsed = self.last_emit_time.elapsed();

        // Emit if: 1% change OR 100ms elapsed
        if percent_change >= 1 || time_elapsed.as_millis() >= 100 {
            self.last_emitted_percent = percent;
            self.last_emit_time = std::time::Instant::now();

            Some(ModelDownloadProgress {
                model: self.model_name.clone(),
                progress: percent,
                stage: DownloadStage::Downloading,
                downloaded_bytes: Some(downloaded_bytes),
                total_bytes: Some(self.total_bytes),
            })
        } else {
            None
        }
    }
final_progress function · rust · L357-L365 (9 LOC)
src-tauri/src/services/model_manager.rs
    fn final_progress(&self) -> ModelDownloadProgress {
        ModelDownloadProgress {
            model: self.model_name.clone(),
            progress: 100,
            stage: DownloadStage::Downloading,
            downloaded_bytes: Some(self.total_bytes),
            total_bytes: Some(self.total_bytes),
        }
    }
download_model_file function · rust · L372-L470 (99 LOC)
src-tauri/src/services/model_manager.rs
async fn download_model_file<F>(
    url: &str,
    dest_path: &Path,
    model_name: String,
    expected_size: u64,
    mut progress_callback: F,
) -> Result<(), String>
where
    F: FnMut(ModelDownloadProgress),
{
    use reqwest::Client;
    use futures_util::StreamExt;
    use tokio::io::AsyncWriteExt;

    println!("[MODEL DOWNLOAD] download_model_file: Starting download from {}", url);

    // Create the parent directory if it doesn't exist
    if let Some(parent) = dest_path.parent() {
        tokio::fs::create_dir_all(parent)
            .await
            .map_err(|e| format!("Failed to create directory: {}", e))?;
    }

    // Create HTTP client
    println!("[MODEL DOWNLOAD] Creating HTTP client...");
    let client = Client::builder()
        .build()
        .map_err(|e| format!("Failed to create HTTP client: {}", e))?;
    println!("[MODEL DOWNLOAD] HTTP client created");

    // Start the download request
    println!("[MODEL DOWNLOAD] Starting HTTP GET request...");
 
delete_model_async function · rust · L484-L491 (8 LOC)
src-tauri/src/services/model_manager.rs
pub async fn delete_model_async(model_name: String) -> Result<(), String> {
    // Run the blocking delete in a thread pool
    tokio::task::spawn_blocking(move || {
        delete_model(&model_name)
    })
    .await
    .map_err(|e| format!("Failed to join task: {}", e))?
}
test_get_available_models function · rust · L498-L508 (11 LOC)
src-tauri/src/services/model_manager.rs
    fn test_get_available_models() {
        let models = get_available_models();
        assert_eq!(models.len(), 5);

        // Check that models are in correct order
        assert_eq!(models[0].name, "tiny");
        assert_eq!(models[1].name, "base");
        assert_eq!(models[2].name, "small");
        assert_eq!(models[3].name, "medium");
        assert_eq!(models[4].name, "large");
    }
test_model_sizes function · rust · L511-L518 (8 LOC)
src-tauri/src/services/model_manager.rs
    fn test_model_sizes() {
        let models = get_available_models();

        // Verify sizes are in ascending order
        for i in 1..models.len() {
            assert!(models[i - 1].size_bytes < models[i].size_bytes);
        }
    }
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
test_get_active_model_default function · rust · L521-L524 (4 LOC)
src-tauri/src/services/model_manager.rs
    fn test_get_active_model_default() {
        let active = get_active_model();
        assert_eq!(active, WhisperModel::Small);
    }
test_set_active_model function · rust · L527-L534 (8 LOC)
src-tauri/src/services/model_manager.rs
    fn test_set_active_model() {
        let temp_dir = std::env::temp_dir();
        let test_models_dir = temp_dir.join("test-whisper-models");

        // This would require mocking the dirs crate
        // For now, we just verify the function signature
        assert!(true);
    }
test_get_download_url function · rust · L537-L541 (5 LOC)
src-tauri/src/services/model_manager.rs
    fn test_get_download_url() {
        let url = get_model_download_url("small").unwrap();
        assert!(url.contains("ggml-small.bin"));
        assert!(url.contains("huggingface.co"));
    }
‹ prevpage 5 / 9next ›