iOS sometimes saves HEIC with .jpeg extension. Pillow fails to open
these as JPEG, so now we fallback to trying pillow-heif directly
when initial open fails.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add pillow-heif dependency for iPhone photo support
- Auto-convert HEIC to JPEG (browsers can't display HEIC)
- Graceful error if pillow-heif not installed
- Handles RGBA/P mode conversion to RGB
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements media upload logging per docs/design/v1.4.1/media-logging-design.md
Changes:
- Add logging to save_media() in starpunk/media.py:
* INFO: Successful uploads with file details
* WARNING: Validation/optimization/variant failures
* ERROR: Unexpected system errors
- Remove duplicate logging in Micropub media endpoint
- Add 5 comprehensive logging tests in TestMediaLogging class
- Bump version to 1.4.1
- Update CHANGELOG.md
All media upload operations now logged for debugging and observability.
Validation errors, optimization failures, and variant generation issues
are tracked at appropriate log levels. Original functionality unchanged.
Test results: 28/28 media tests pass, 5 new logging tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Following design approved by architect in docs/design/v1.4.0/
Changes to starpunk/media.py:
- Update delete_media() to fetch and delete variant files from disk
- Query media_variants table before deletion for file paths
- Use best-effort cleanup with try/except for each file
- Log individual file deletion failures as warnings
- Update final log to show total files deleted (original + variants)
- Update module docstring to reflect v1.4.0 capabilities:
* 50MB max upload, 10MB max output
* Image variants (thumb, small, medium, large)
* Tiered resize strategy
This fixes the issue where variant files were left orphaned on disk
when media was deleted. The database CASCADE already deleted variant
records, but the physical files remained.
All tests pass: uv run pytest tests/test_media_upload.py -v (23/23)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement automatic generation of multiple image sizes for responsive
delivery and enhanced feed optimization.
Changes:
- Add migration 009 for media_variants table with CASCADE delete
- Define variant specs: thumb (150x150 crop), small (320px), medium (640px), large (1280px)
- Implement generate_variant() with center crop for thumbnails and aspect-preserving resize
- Implement generate_all_variants() with try/except cleanup, pass year/month/optimized_bytes explicitly
- Update save_media() to generate all variants after saving original
- Update get_note_media() to include variants dict (backwards compatible - only when variants exist)
- Record original as 'original' variant type
Technical details:
- Variants use explicit year/month parameters to avoid fragile path traversal
- Pass optimized_bytes to avoid redundant file I/O
- File cleanup on variant generation failure
- Skip generating variants larger than source image
- variants key only added to response when variants exist (pre-v1.4.0 compatibility)
All existing tests pass. Phase 2 complete.
Per design document: /home/phil/Projects/starpunk/docs/design/v1.4.0/media-implementation-design.md
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement tiered resize strategy for large images per v1.4.0 design:
Changes:
- Increase MAX_FILE_SIZE from 10MB to 50MB
- Add MAX_OUTPUT_SIZE constant (10MB target after optimization)
- Add MIN_QUALITY and MIN_DIMENSION constants
- Add get_optimization_params() for tiered strategy:
- <=10MB: 2048px max, 95% quality
- 10-25MB: 1600px max, 90% quality
- 25-50MB: 1280px max, 85% quality
- Update optimize_image() signature to return 4-tuple (img, w, h, bytes)
- Implement iterative quality reduction if output >10MB
- Add animated GIF detection and size check in validate_image()
- Update save_media() to use new optimize_image() return value
- Fix GIF format preservation during optimization
- Update tests to match new optimize_image() signature
All existing tests pass. Ready for Phase 2 (Image Variants).
Following design in:
/home/phil/Projects/starpunk/docs/design/v1.4.0/media-implementation-design.md
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>