-
Notifications
You must be signed in to change notification settings - Fork 0
Code Review Bench PR #14128 - feat(cli): UTExportedTypeDeclarations support for file associations #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Code Review Bench PR #14128 - feat(cli): UTExportedTypeDeclarations support for file associations #12
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| "tauri-cli": minor:feat | ||
| "@tauri-apps/cli": minor:feat | ||
| --- | ||
|
|
||
| Added support to defining the content type of the declared file association on macOS (maps to LSItemContentTypes property). |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| "tauri-cli": minor:feat | ||
| "@tauri-apps/cli": minor:feat | ||
| --- | ||
|
|
||
| Added support to defining the metadata for custom types declared in `tauri.conf.json > bundle > fileAssociations > exportedType` via the `UTExportedTypeDeclarations` Info.plist property. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "tauri-utils": minor:feat | ||
| --- | ||
|
|
||
| Added `FileAssociation::exported_type` and `FileAssociation::content_types` for better support to defining custom types on macOS. |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -268,29 +268,89 @@ fn create_info_plist( | |||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if let Some(associations) = settings.file_associations() { | ||||||||||||||||||||||||||||||||||||||||||
| let exported_associations = associations | ||||||||||||||||||||||||||||||||||||||||||
| .iter() | ||||||||||||||||||||||||||||||||||||||||||
| .filter_map(|association| { | ||||||||||||||||||||||||||||||||||||||||||
| association.exported_type.as_ref().map(|exported_type| { | ||||||||||||||||||||||||||||||||||||||||||
| let mut dict = plist::Dictionary::new(); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| dict.insert( | ||||||||||||||||||||||||||||||||||||||||||
| "UTTypeIdentifier".into(), | ||||||||||||||||||||||||||||||||||||||||||
| exported_type.identifier.clone().into(), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| if let Some(description) = &association.description { | ||||||||||||||||||||||||||||||||||||||||||
| dict.insert("UTTypeDescription".into(), description.clone().into()); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| if let Some(content_types) = &association.content_types { | ||||||||||||||||||||||||||||||||||||||||||
| dict.insert( | ||||||||||||||||||||||||||||||||||||||||||
| "UTTypeConformsTo".into(), | ||||||||||||||||||||||||||||||||||||||||||
| plist::Value::Array(content_types.iter().map(|s| s.clone().into()).collect()), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| let mut specification = plist::Dictionary::new(); | ||||||||||||||||||||||||||||||||||||||||||
| specification.insert( | ||||||||||||||||||||||||||||||||||||||||||
| "public.filename-extension".into(), | ||||||||||||||||||||||||||||||||||||||||||
| plist::Value::Array( | ||||||||||||||||||||||||||||||||||||||||||
| association | ||||||||||||||||||||||||||||||||||||||||||
| .ext | ||||||||||||||||||||||||||||||||||||||||||
| .iter() | ||||||||||||||||||||||||||||||||||||||||||
| .map(|s| s.to_string().into()) | ||||||||||||||||||||||||||||||||||||||||||
| .collect(), | ||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| if let Some(mime_type) = &association.mime_type { | ||||||||||||||||||||||||||||||||||||||||||
| specification.insert("public.mime-type".into(), mime_type.clone().into()); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| dict.insert("UTTypeTagSpecification".into(), specification.into()); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| plist::Value::Dictionary(dict) | ||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||
| .collect::<Vec<_>>(); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if !exported_associations.is_empty() { | ||||||||||||||||||||||||||||||||||||||||||
| plist.insert( | ||||||||||||||||||||||||||||||||||||||||||
| "UTExportedTypeDeclarations".into(), | ||||||||||||||||||||||||||||||||||||||||||
| plist::Value::Array(exported_associations), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| plist.insert( | ||||||||||||||||||||||||||||||||||||||||||
| "CFBundleDocumentTypes".into(), | ||||||||||||||||||||||||||||||||||||||||||
| plist::Value::Array( | ||||||||||||||||||||||||||||||||||||||||||
| associations | ||||||||||||||||||||||||||||||||||||||||||
| .iter() | ||||||||||||||||||||||||||||||||||||||||||
| .map(|association| { | ||||||||||||||||||||||||||||||||||||||||||
| let mut dict = plist::Dictionary::new(); | ||||||||||||||||||||||||||||||||||||||||||
| dict.insert( | ||||||||||||||||||||||||||||||||||||||||||
| "CFBundleTypeExtensions".into(), | ||||||||||||||||||||||||||||||||||||||||||
| plist::Value::Array( | ||||||||||||||||||||||||||||||||||||||||||
| association | ||||||||||||||||||||||||||||||||||||||||||
| .ext | ||||||||||||||||||||||||||||||||||||||||||
| .iter() | ||||||||||||||||||||||||||||||||||||||||||
| .map(|ext| ext.to_string().into()) | ||||||||||||||||||||||||||||||||||||||||||
| .collect(), | ||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if association.ext.is_empty() { | ||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚨 Bug: Inverted condition: CFBundleTypeExtensions added only when emptyThe condition on line 328 is This is the exact opposite of the intended behavior. The original code unconditionally inserted the extensions. The new code was meant to make it conditional (skip when empty), but the negation is missing. Impact: All macOS file associations with extensions will be broken — Was this helpful? React with 👍 / 👎
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||
| dict.insert( | ||||||||||||||||||||||||||||||||||||||||||
| "CFBundleTypeExtensions".into(), | ||||||||||||||||||||||||||||||||||||||||||
| plist::Value::Array( | ||||||||||||||||||||||||||||||||||||||||||
| association | ||||||||||||||||||||||||||||||||||||||||||
| .ext | ||||||||||||||||||||||||||||||||||||||||||
| .iter() | ||||||||||||||||||||||||||||||||||||||||||
| .map(|ext| ext.to_string().into()) | ||||||||||||||||||||||||||||||||||||||||||
| .collect(), | ||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if let Some(content_types) = &association.content_types { | ||||||||||||||||||||||||||||||||||||||||||
| dict.insert( | ||||||||||||||||||||||||||||||||||||||||||
| "LSItemContentTypes".into(), | ||||||||||||||||||||||||||||||||||||||||||
| plist::Value::Array(content_types.iter().map(|s| s.to_string().into()).collect()), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| dict.insert( | ||||||||||||||||||||||||||||||||||||||||||
| "CFBundleTypeName".into(), | ||||||||||||||||||||||||||||||||||||||||||
| association | ||||||||||||||||||||||||||||||||||||||||||
| .name | ||||||||||||||||||||||||||||||||||||||||||
| .as_ref() | ||||||||||||||||||||||||||||||||||||||||||
| .unwrap_or(&association.ext[0].0) | ||||||||||||||||||||||||||||||||||||||||||
| .expect("File association must have a name") | ||||||||||||||||||||||||||||||||||||||||||
| .to_string() | ||||||||||||||||||||||||||||||||||||||||||
| .into(), | ||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
348
to
356
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚨 Bug: Panic when file association has no
|
||||||||||||||||||||||||||||||||||||||||||
| dict.insert( | |
| "CFBundleTypeName".into(), | |
| association | |
| .name | |
| .as_ref() | |
| .unwrap_or(&association.ext[0].0) | |
| .expect("File association must have a name") | |
| .to_string() | |
| .into(), | |
| ); | |
| dict.insert( | |
| "CFBundleTypeName".into(), | |
| association | |
| .name | |
| .as_ref() | |
| .or(association.ext.first().map(|e| &e.0)) | |
| .cloned() | |
| .unwrap_or_default() | |
| .into(), | |
| ); |
- Apply suggested fix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚨 Bug: Wrong field used for UTTypeConformsTo in exported type
In the
UTExportedTypeDeclarationsgeneration (lines 284-289), the code usesassociation.content_typesto populateUTTypeConformsTo. However,content_typesmaps toLSItemContentTypesand represents what content types the app handles. The correct field isexported_type.conforms_to, which is the dedicated field onExportedFileAssociationfor this purpose.The
ExportedFileAssociationstruct has aconforms_to: Option<Vec<String>>field (line 1216 in config.rs) that is never read anywhere in the bundler code. Meanwhile, the example config intauri.conf.jsonputsconformsToinsideexportedType, confirming it should beexported_type.conforms_to.Impact: The
UTTypeConformsToplist entry will never be generated correctly. Even whenconformsTois configured in the exported type, it is completely ignored. IfcontentTypeshappens to be set on the association, its values will be incorrectly used as conformance declarations.Was this helpful? React with 👍 / 👎