{"id":28543604,"url":"https://github.com/karn/shrinkwrap","last_synced_at":"2025-07-20T07:05:06.875Z","repository":{"id":297349174,"uuid":"996454435","full_name":"Karn/shrinkwrap","owner":"Karn","description":"Simple PDF compression inspired by Lightweight PDF","archived":false,"fork":false,"pushed_at":"2025-06-05T02:51:31.000Z","size":183,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-05T06:10:46.304Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Karn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-05T01:19:51.000Z","updated_at":"2025-06-05T02:51:33.000Z","dependencies_parsed_at":"2025-06-08T07:02:55.600Z","dependency_job_id":null,"html_url":"https://github.com/Karn/shrinkwrap","commit_stats":null,"previous_names":["karn/shrinkwrap"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Karn/shrinkwrap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Karn%2Fshrinkwrap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Karn%2Fshrinkwrap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Karn%2Fshrinkwrap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Karn%2Fshrinkwrap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Karn","download_url":"https://codeload.github.com/Karn/shrinkwrap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Karn%2Fshrinkwrap/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266081239,"owners_count":23873511,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-09T21:30:28.093Z","updated_at":"2025-07-20T07:05:06.865Z","avatar_url":"https://github.com/Karn.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Shrinkwrap - PDF Compression Tool\n\nA modern, Kotlin-based desktop application for compressing PDF files using Ghostscript. Built with Compose Multiplatform for a native desktop experience.\n\n## 🚀 Features\n\n- **Drag \u0026 Drop Interface**: Simply drag PDF files onto the application\n- **Clipboard Support**: Paste files directly with ⌘+V (macOS)\n- **Real-time Progress**: Visual feedback for compression status\n- **Batch Processing**: Handle multiple files simultaneously\n- **Compression Stats**: Shows file size reduction percentages\n- **Finder Integration**: Click files to reveal in Finder\n\n## 🏗️ Architecture\n\nThe application follows a clean, modular architecture designed for maintainability and testability:\n\n```\nsrc/main/kotlin/\n├── Main.kt                     # Application entry point \u0026 UI orchestration\n├── MainViewModel.kt            # State management \u0026 coordination\n├── domain/                     # Business logic layer\n│   ├── CompressionService.kt   # PDF compression interface \u0026 implementation\n│   └── FileProcessingState.kt  # Domain models \u0026 state\n├── infrastructure/             # External dependencies\n│   └── CommandExecutor.kt      # System command execution abstraction\n├── ui/                        # User interface components\n│   ├── components/\n│   │   ├── DragDropArea.kt     # Drag \u0026 drop functionality\n│   │   └── FileListItem.kt     # File list item component\n│   └── DashedBorder.kt         # UI utility for dashed borders\n└── utils/                     # Common utilities\n    └── FileUtils.kt           # File operations \u0026 formatting\n```\n\n### Key Architectural Principles\n\n- **Separation of Concerns**: Domain, UI, and Infrastructure layers are clearly separated\n- **Dependency Injection**: Services can be easily mocked and tested\n- **Interface Segregation**: Clean interfaces enable easy testing and extension\n- **Single Responsibility**: Each class has one clear purpose\n\n## 🛠️ Getting Started\n\n### Prerequisites\n\n- **Kotlin/JVM**: Project uses Kotlin with Compose Desktop\n- **Ghostscript**: Required for PDF compression functionality\n\n  ```bash\n  # macOS\n  brew install ghostscript\n\n  # Ubuntu/Debian\n  sudo apt-get install ghostscript\n  ```\n\n### Building \u0026 Running\n\n```bash\n# Clone the repository\ngit clone \u003crepository-url\u003e\ncd shrinkwrap\n\n# Build the application\n./gradlew build\n\n# Run the application\n./gradlew run\n\n# Create native distribution\n./gradlew createDistributable\n```\n\n## 🧪 Testing Strategy\n\nThe modular architecture enables comprehensive testing:\n\n### Unit Tests\n\n```kotlin\n// Service layer testing\nclass CompressionServiceTest {\n    @Test\n    fun `should compress valid PDF file`() {\n        val mockCommandExecutor = mockk\u003cCommandExecutor\u003e()\n        val service = GhostscriptCompressionService(mockCommandExecutor)\n        // Test without system dependencies\n    }\n}\n\n// State management testing\nclass MainViewModelTest {\n    @Test\n    fun `should update state when file is added`() {\n        val mockService = mockk\u003cCompressionService\u003e()\n        val viewModel = MainViewModel(mockService)\n        // Test state transitions\n    }\n}\n```\n\n### Integration Tests\n\n- Test UI components with test state\n- Test end-to-end file processing workflows\n- Test error handling scenarios\n\n## 🔮 Future Enhancements\n\n### High Priority\n\n#### 1. **Compression Quality Settings**\n\n- Add UI controls for high/medium/low quality selection\n- Remember user preferences\n- Quality preview before compression\n\n#### 2. **Enhanced Error Handling**\n\n- User-friendly error messages\n- Retry mechanisms for failed compressions\n- Better validation feedback\n\n#### 3. **Progress \u0026 Performance**\n\n- Detailed progress bars for large files\n- Compression speed metrics\n- Estimated time remaining\n\n### Medium Priority\n\n#### 4. **Multiple Compression Backends**\n\n```kotlin\n// Easy to implement with current architecture\nclass PDFtkCompressionService : CompressionService { ... }\nclass ImageMagickCompressionService : CompressionService { ... }\n```\n\n#### 5. **Batch Operations**\n\n- Select compression quality per batch\n- Pause/resume batch processing\n- Export compression reports\n\n#### 6. **File Management**\n\n- Original file backup options\n- Custom output directory selection\n- File name templates (e.g., `{original}_compressed.pdf`)\n\n#### 7. **Advanced Features**\n\n- PDF optimization beyond compression\n- Image quality adjustments within PDFs\n- Metadata preservation options\n\n### Lower Priority\n\n#### 8. **User Experience**\n\n- Dark/light theme toggle\n- Keyboard shortcuts for common actions\n- Recent files list\n- Undo/redo functionality\n\n#### 9. **Analytics \u0026 Reporting**\n\n- Compression statistics dashboard\n- Export compression reports\n- Historical data tracking\n\n#### 10. **Cross-Platform Enhancements**\n\n- Windows Explorer integration\n- Linux file manager integration\n- Platform-specific optimizations\n\n### Technical Enhancements\n\n#### 11. **Performance Optimizations**\n\n- Memory-efficient processing for large files\n- Background compression queue\n- Multi-threaded processing improvements\n\n#### 12. **Configuration System**\n\n- Settings persistence\n- Custom Ghostscript parameters\n- Advanced user configurations\n\n#### 13. **Plugin Architecture**\n\n- Custom compression algorithms\n- Third-party integrations\n- Extension marketplace\n\n## 🤝 Contributing\n\n### Code Style\n\n- Follow Kotlin coding conventions\n- Use meaningful variable and function names\n- Add KDoc comments for public APIs\n- Keep functions focused and small\n\n### Testing Requirements\n\n- Unit tests for all business logic\n- UI tests for interactive components\n- Integration tests for file operations\n- Maintain \u003e80% code coverage\n\n### Architecture Guidelines\n\n- Keep domain logic pure (no UI or infrastructure dependencies)\n- Use dependency injection for testability\n- Create reusable UI components\n- Handle errors gracefully with meaningful messages\n\n## 📋 Implementation Notes\n\n### Adding New Compression Backends\n\n1. Implement `CompressionService` interface\n2. Add to dependency injection in `MainViewModel`\n3. Add UI selection controls\n4. Update tests\n\n### Adding New UI Components\n\n1. Create in `ui/components/` package\n2. Follow existing component patterns\n3. Make components reusable and configurable\n4. Add preview functions for development\n\n### Performance Considerations\n\n- Large files should be processed in chunks\n- UI should remain responsive during processing\n- Memory usage should be monitored for batch operations\n\n## 📝 License\n\n[Add your license information here]\n\n## 🙏 Acknowledgments\n\n- [Compose Multiplatform](https://github.com/JetBrains/compose-multiplatform) for the UI framework\n- [Ghostscript](https://www.ghostscript.com/) for PDF compression engine\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarn%2Fshrinkwrap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarn%2Fshrinkwrap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarn%2Fshrinkwrap/lists"}