2026-06-09 19:58:07 +08:00

106 lines
3.5 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::error::DocumentError;
use crate::material_type::MaterialType;
/// Describes how an Office document should be previewed.
///
/// - Word/Excel → PlatformPreview (iOS: QLPreviewController / WKWebView)
/// - PowerPoint → ExternalOpen (open in system app)
/// - Future: ServerConvertedPdf (server converts Office→PDF)
#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Enum)]
pub enum OfficePreviewStrategy {
/// Use OS-native preview (QLPreviewController on iOS, Intent on Android)
PlatformPreview,
/// Open in external app (e.g., PowerPoint app for .pptx)
ExternalOpen,
/// Server-side conversion to PDF, then preview the PDF
ServerConvertedPdf,
/// Format not supported for preview
Unsupported,
}
/// Preview configuration for an Office document.
#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
pub struct OfficePreviewConfig {
pub material_type: MaterialType,
pub strategy: OfficePreviewStrategy,
pub file_size: u64,
/// Whether the document can be searched after server conversion
pub supports_search_after_conversion: bool,
}
/// Get the recommended preview strategy for an Office material type.
pub fn get_office_preview_config(
material_type: &MaterialType,
file_size: u64,
) -> Result<OfficePreviewConfig, DocumentError> {
let (strategy, supports_search) = match material_type {
MaterialType::Word | MaterialType::Excel => {
(OfficePreviewStrategy::PlatformPreview, true)
}
MaterialType::PowerPoint => {
(OfficePreviewStrategy::ExternalOpen, true)
}
_ => {
return Err(DocumentError::UnsupportedFormat(
"not an Office document type".into()
));
}
};
Ok(OfficePreviewConfig {
material_type: material_type.clone(),
strategy,
file_size,
supports_search_after_conversion: supports_search,
})
}
/// Check if a material type is an Office document.
pub fn is_office_type(mt: &MaterialType) -> bool {
matches!(
mt,
MaterialType::Word | MaterialType::Excel | MaterialType::PowerPoint
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_word_preview_strategy() {
let config = get_office_preview_config(&MaterialType::Word, 1024).unwrap();
assert!(matches!(config.strategy, OfficePreviewStrategy::PlatformPreview));
assert!(config.supports_search_after_conversion);
}
#[test]
fn test_excel_preview_strategy() {
let config = get_office_preview_config(&MaterialType::Excel, 2048).unwrap();
assert!(matches!(config.strategy, OfficePreviewStrategy::PlatformPreview));
}
#[test]
fn test_powerpoint_preview_strategy() {
let config = get_office_preview_config(&MaterialType::PowerPoint, 512).unwrap();
assert!(matches!(config.strategy, OfficePreviewStrategy::ExternalOpen));
}
#[test]
fn test_non_office_rejected() {
assert!(get_office_preview_config(&MaterialType::Markdown, 100).is_err());
assert!(get_office_preview_config(&MaterialType::Pdf, 100).is_err());
}
#[test]
fn test_is_office_type() {
assert!(is_office_type(&MaterialType::Word));
assert!(is_office_type(&MaterialType::Excel));
assert!(is_office_type(&MaterialType::PowerPoint));
assert!(!is_office_type(&MaterialType::Pdf));
assert!(!is_office_type(&MaterialType::Markdown));
}
}