diff --git a/src/launchpad/artifacts/apple/zipped_xcarchive.py b/src/launchpad/artifacts/apple/zipped_xcarchive.py index 99576cb9..0a585df9 100644 --- a/src/launchpad/artifacts/apple/zipped_xcarchive.py +++ b/src/launchpad/artifacts/apple/zipped_xcarchive.py @@ -430,18 +430,14 @@ def _parse_asset_element(self, item: dict[str, Any], parent_path: Path) -> Asset colorspace = item.get("colorspace") file_extension = Path(filename).suffix.lower() - full_path = None - - if filename: - if file_extension in {".png", ".jpg", ".jpeg", ".heic", ".heif"}: - potential_path = parent_path / f"{image_id}{file_extension}" - if potential_path.exists(): - full_path = potential_path - elif not file_extension: - # No extension, try .png as default (for some asset catalog entries) - potential_path = parent_path / f"{image_id}.png" - if potential_path.exists(): - full_path = potential_path + if filename and file_extension in {".png", ".jpg", ".jpeg", ".heic", ".heif"}: + potential_path = parent_path / f"{image_id}{file_extension}" + if potential_path.exists(): + full_path = potential_path + else: + full_path = None + else: + full_path = None return AssetCatalogElement( name=name, diff --git a/src/launchpad/size/insights/apple/alternate_icons_optimization.py b/src/launchpad/size/insights/apple/alternate_icons_optimization.py index 6cd1eaf2..28efb93b 100644 --- a/src/launchpad/size/insights/apple/alternate_icons_optimization.py +++ b/src/launchpad/size/insights/apple/alternate_icons_optimization.py @@ -2,7 +2,6 @@ import io -from pathlib import Path from typing import List from PIL import Image @@ -69,8 +68,3 @@ def _resize_icon_for_analysis(self, img: Image.Image) -> Image.Image: return img.resize((self.IPHONE_3X_ICON_SIZE, self.IPHONE_3X_ICON_SIZE), Image.Resampling.LANCZOS).resize( (self.APP_STORE_ICON_SIZE, self.APP_STORE_ICON_SIZE), Image.Resampling.LANCZOS ) - - def _is_alternate_icon_file(self, file_info: FileInfo, alternate_icon_names: set[str]) -> bool: - # Some asset catalog entries have no extension, so we include "other" in the OPTIMIZABLE_FORMATS - file_type_match = file_info.file_type.lower() in (self.OPTIMIZABLE_FORMATS | {"other"}) - return file_type_match and Path(file_info.path).stem in alternate_icon_names diff --git a/src/launchpad/size/insights/apple/image_optimization.py b/src/launchpad/size/insights/apple/image_optimization.py index 632748ec..cb1b2a7d 100644 --- a/src/launchpad/size/insights/apple/image_optimization.py +++ b/src/launchpad/size/insights/apple/image_optimization.py @@ -182,6 +182,24 @@ def _check_heic_minification(self, img: Image.Image, file_size: int) -> _Optimiz logger.exception("HEIC image minification failed") return None + def _is_alternate_icon_file(self, file_info: FileInfo, alternate_icon_names: set[str]) -> bool: + file_type_match = file_info.file_type.lower() in self.OPTIMIZABLE_FORMATS + + if not file_type_match: + return False + + stem = Path(file_info.path).stem + parent_str = str(Path(file_info.path).parent) + + if stem in alternate_icon_names: + return True + + for name in alternate_icon_names: + if parent_str == f"Assets.car/{name}": + return True + + return False + class ImageOptimizationInsight(BaseImageOptimizationInsight): """Analyse image optimisation opportunities in iOS apps.""" @@ -225,4 +243,14 @@ def _is_optimizable_image_file( return not Path(file_info.path).name.startswith(("AppIcon", "iMessage App Icon")) stem = Path(file_info.path).stem - return stem != primary_icon_name and stem not in alternate_icon_names + parent_str = str(Path(file_info.path).parent) + + # Exclude primary icon + if stem == primary_icon_name or parent_str == f"Assets.car/{primary_icon_name}": + return False + + # Exclude alternate icons (they have their own insight) + if self._is_alternate_icon_file(file_info, alternate_icon_names): + return False + + return True