106 lines
3.5 KiB
Rust
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));
|
|
}
|
|
}
|