A cross-platform (iOS & Android) Flutter app for creating curated photo galleries with secure presentation mode. When presenting photos, viewers see only selected photos and cannot exit without locking the device.
- Photo Collections: Create unlimited named collections with unlimited photos
- Multi-source Import: Add photos from local gallery, iCloud, Google Photos, or any source
- Share Sheet Integration: Share photos directly from any app to Nokku temp gallery
- Secure Presentation Mode: Full-screen, immersive photo viewing with device lock on exit
- Native Feel: Platform-specific UI (iOS Photos style / Android Gallery style)
- Native horizontal swipe navigation (infinite loop)
- Tap-on-sides support for navigation
- Optional pinch-to-zoom
- Optional photo counter ("3 of 10")
- Auto-advance slideshow with configurable intervals
- Auto-lock timer for hands-free viewing
- Smooth, 60fps transitions
- Android: Device Admin integration for automatic device locking on exit attempts
- iOS: Guided Access mode support with in-app instructions
- Intercepts back button, home gesture, and app switcher attempts
- Immediate device lock on any exit attempt during presentation
Presentation Settings:
- Pinch-to-zoom: On/Off (default: Off)
- Photo counter: Show/Hide (default: Hide)
- Auto-advance: On/Off with intervals (3s, 5s, 10s, 30s)
- Auto-lock timer: 1, 2, 5, 10, 15 minutes or disabled
Display Settings:
- Theme: System/Light/Dark
- Transition animations: Enable/Disable
- Flutter SDK (3.0.0 or higher)
- Xcode 14+ (for iOS development)
- Android Studio / Android SDK (for Android development)
- CocoaPods (for iOS dependencies)
-
Clone and navigate to the project:
cd safe_gallery -
Install dependencies:
flutter pub get
-
iOS Setup:
cd ios pod install cd ..
-
Run on device/emulator:
# iOS flutter run -d ios # Android flutter run -d android
Device Admin Permission (Required for device locking):
- After installing the app, go to Settings
- Tap "Device Admin" under Security section
- Grant device admin permission
- Now the app can lock your device when exiting presentation mode
Permissions:
- Photo library access: Requested on first launch
- Device admin: Manually enabled in Settings
Guided Access Setup (Recommended for full security):
- Go to iOS Settings > Accessibility > Guided Access
- Toggle Guided Access ON
- Set a passcode
- When in presentation mode:
- Triple-click home/side button to start Guided Access
- Triple-click again to exit (requires passcode)
Permissions:
- Photo library access: Requested on first launch
- Open Nokku temp gallery
- Tap the "+" button (Android) or "Create Collection" (iOS)
- Enter a collection name
- Select photos from your gallery
- Tap "Add" to save
- Tap a collection from the home screen
- App enters full-screen presentation mode
- Swipe left/right to navigate (infinite loop)
- Tap left/right sides to navigate
- Long-press the close button (top-right) to exit and lock device
- Open any app with photos (Gallery, WhatsApp, etc.)
- Select photos and tap "Share"
- Choose "Nokku temp gallery"
- Photos open immediately in presentation mode
Rename: Long-press collection → "Rename" Add Photos: Long-press collection → "Add Photos" Delete: Long-press collection → "Delete"
safe_gallery/
├── lib/
│ ├── models/ # Data models
│ │ ├── collection.dart
│ │ ├── photo_item.dart
│ │ └── app_settings.dart
│ ├── services/ # Business logic
│ │ ├── database_service.dart
│ │ ├── photo_service.dart
│ │ ├── lock_service.dart
│ │ └── settings_service.dart
│ ├── providers/ # State management
│ │ └── app_provider.dart
│ ├── screens/ # UI screens
│ │ ├── collections_screen.dart
│ │ ├── presentation_screen.dart
│ │ ├── photo_picker_screen.dart
│ │ └── settings_screen.dart
│ └── main.dart
├── android/
│ └── app/src/main/kotlin/com/safegallery/
│ ├── MainActivity.kt # Platform channel implementation
│ └── DeviceAdminReceiver.kt # Device admin receiver
└── ios/
└── Runner/
└── AppDelegate.swift # Platform channel implementation
- Framework: Flutter 3.x
- State Management: Provider
- Database: SQLite (sqflite)
- Photo Access: photo_manager
- Share Intent: receive_sharing_intent
- Platform Channels: Custom implementation for device locking
- Flutter over Native: Single codebase, excellent performance, rich widget library
- SQLite for Storage: Reliable, fast, supports complex queries for collections
- Platform Channels for Locking: Native Android/iOS APIs for device control
- Provider for State: Simple, efficient, recommended by Flutter team
- Lazy Loading: Images loaded on-demand for memory efficiency
- Lazy Image Loading: Photos loaded only when visible
- Thumbnail Generation: 200x200 thumbnails for grid views
- Image Caching: Automatic caching via photo_manager
- 60fps Target: Smooth animations and transitions
- Battery Optimization: Minimal background processing
- Local Storage Only: All data stored locally, no cloud sync
- No Analytics: Zero tracking or data collection
- Photo Access: Read-only access to photo library
- Device Lock: Prevents unauthorized access during presentation
- Cannot programmatically lock device: iOS security restriction
- Requires Guided Access: User must manually enable for full lock mode
- System gestures: Cannot fully block without Guided Access
- Requires Device Admin: User must grant permission manually
- Some launchers: May bypass lock on certain custom Android launchers
Solution: Enable Device Admin in Settings → Security → Device Admin
Solution: Grant photo library permission in device settings
Solution: Reinstall app (share intent registered during installation)
Solution: Enable and use Guided Access (triple-click home button)
flutter build apk --release
# or
flutter build appbundle --releaseOutput: build/app/outputs/flutter-apk/app-release.apk
flutter build ios --releaseThen open ios/Runner.xcworkspace in Xcode and archive.
- Cloud backup for collections (optional)
- Password protection for individual collections
- Video support
- Collection sharing (export/import)
- Multiple themes
- Advanced editing (crop, rotate)
- Photo metadata display
This is a personal project, but suggestions and bug reports are welcome!
MIT License - See LICENSE file for details
For issues or questions:
- Open an issue on GitHub
- Check the troubleshooting section above
Built with Flutter ❤️ for iOS and Android