build: github acik kaynak hazirligi — LICENSE/CI/topluluk dosyalari eklendi, binary'ler takipten cikarildi, README EN, kok dokumanlar docs/'a tasindi
This commit is contained in:
1 parent
cd3f573f57
commit
8972ef7225
35 files changed
+560
-151
No files matched your search
@@ -0,0 +1,209 @@
|
||||
# Implementation — imajViewer
|
||||
|
||||
> Teknik uygulama dokümanı
|
||||
> Versiyon: 1.0
|
||||
|
||||
---
|
||||
|
||||
## 1. Mimari Genel Bakış
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ Flutter App │
|
||||
│ ┌────────────┐ ┌────────────────────────────┐ │
|
||||
│ │ window_mgr │ │ ViewerScreen │ │
|
||||
│ │ (frameless)│ │ ┌──────────────────────┐ │ │
|
||||
│ └────────────┘ │ │ CustomTitleBar │ │ │
|
||||
│ │ │ (minimize, close) │ │ │
|
||||
│ │ ├──────────────────────┤ │ │
|
||||
│ │ │ ImageCanvas │ │ │
|
||||
│ │ │ (InteractiveViewer) │ │ │
|
||||
│ │ │ - Scroll → Zoom │ │ │
|
||||
│ │ │ - Drag → Pan │ │ │
|
||||
│ │ └──────────────────────┘ │ │
|
||||
│ └────────────────────────────┘ │
|
||||
│ ┌────────────────────────────────────────────┐ │
|
||||
│ │ ImageCacheManager │ │
|
||||
│ │ - PrecacheImage │ │
|
||||
│ │ - LRU eviction (> N images) │ │
|
||||
│ │ - File → Memory → GPU Texture │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
└──────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 2. Bileşen Ağacı (Widget Tree)
|
||||
|
||||
```
|
||||
MaterialApp (dark theme)
|
||||
└── ViewerScreen (StatefulWidget)
|
||||
├── Stack
|
||||
│ ├── InteractiveViewer (zoom + pan)
|
||||
│ │ └── RawImage (resim)
|
||||
│ ├── CustomTitleBar (Positioned: top-right)
|
||||
│ │ ├── IconButton (minimize)
|
||||
│ │ └── IconButton (close)
|
||||
│ └── (koyu arka plan)
|
||||
└── DragTarget (sürükle-bırak dosya alanı)
|
||||
```
|
||||
|
||||
## 3. Data Flow
|
||||
|
||||
```
|
||||
Kullanıcı dosya bırakır / açar
|
||||
│
|
||||
▼
|
||||
ViewerScreen.dragResult / openFileDialog
|
||||
│
|
||||
▼
|
||||
ImageList (List<String> filePaths)
|
||||
│
|
||||
▼
|
||||
preloadImages() → ImageCache'e ekle
|
||||
│
|
||||
▼
|
||||
Indexed, currentIndex değişince
|
||||
│
|
||||
▼
|
||||
InteractiveViewer.builder → Image.file(path)
|
||||
│
|
||||
▼
|
||||
Flutter ImageCache → GPU Texture → Render
|
||||
```
|
||||
|
||||
## 4. Adım Adım Uygulama
|
||||
|
||||
### Adım 1: Proje İskeleti
|
||||
- `flutter create imajViewer`
|
||||
- `--platforms=linux` ile oluştur
|
||||
- Temele dark tema, frameless window ekle
|
||||
|
||||
**Dosyalar:** `main.dart`, `app.dart`
|
||||
|
||||
### Adım 2: window_manager Kurulumu
|
||||
- pubspec.yaml: `window_manager: ^0.4.3`
|
||||
- `main()` içinde `windowManager.ensureInitialized()`
|
||||
- `waitUntilReadyToShow` → frameless ayarları:
|
||||
- `setTitleBarStyle(TitleBarStyle.hidden)`
|
||||
- `setSize(Size(1280, 800))`
|
||||
- `setMinimumSize(Size(800, 600))`
|
||||
- `setBackgroundColor(Colors.transparent)`
|
||||
- Linux'ta `linux/my_app.cc`'de window_manager için ek ayar gerekebilir
|
||||
|
||||
**Dosyalar:** `lib/main.dart`, `pubspec.yaml`
|
||||
|
||||
### Adım 3: CustomTitleBar Widget
|
||||
- Sağ üst köşede, sabit konumda
|
||||
- Siyah yarı saydam arka plan
|
||||
- minimize (—) ve kapat (X) butonları
|
||||
- **Püf nokta:** Butonların üzerine gelince InteractiveViewer zoom yapmamalı
|
||||
- `AbsorbPointer` veya `IgnorePointer` ile InteractiveViewer etkileşimini engelle
|
||||
- Pencere boyutlandırma ve sürükleme kenarlıkları (window_manager'in `setResizable` özelliği)
|
||||
|
||||
**Dosya:** `lib/widgets/custom_title_bar.dart`
|
||||
|
||||
### Adım 4: ImageCanvas (Ana Görüntüleme)
|
||||
- `InteractiveViewer` widget'ı
|
||||
- `boundaryMargin: EdgeInsets.all(double.infinity)` → sınırsız kaydırma
|
||||
- `minScale: 0.1`, `maxScale: 10.0`
|
||||
- `onInteractionUpdate` → zoom oranını göstermek için (ops.)
|
||||
- `transformationController` ile programatik zoom kontrolü
|
||||
- Mouse wheel event: `Listener` ile `onPointerSignal` yakala
|
||||
- `PointerScrollEvent` → transformationController ile zoom
|
||||
- Fare imlecinin resim üzerindeki konumuna göre zoom odağı
|
||||
|
||||
**Püf nokta:**
|
||||
`InteractiveViewer`'ın default scroll-to-zoom desteği vardır ama imleç odağında zoom
|
||||
için `TransformationController`'a manuel matrix hesaplaması yapmak gerekir.
|
||||
|
||||
**Dosya:** `lib/widgets/image_canvas.dart`
|
||||
|
||||
### Adım 5: Resim Yönetimi (ImageManager)
|
||||
- `ChangeNotifier` ile state yönetimi
|
||||
- Dışarıdan dosya eklendiğinde `notifyListeners()` + `precacheImage()`
|
||||
- `ImageCache.maximumSize` ve `maximumSizeBytes` ayarı
|
||||
- **Performans stratejisi:**
|
||||
- Sadece görünen resim bellekte tutulur
|
||||
- 12+ resim için `ImageCache.maximumSizeBytes` = 512MB
|
||||
- Resim değiştirince önceki resmin cache'ini düşürmeye gerek yok (Flutter LRU)
|
||||
- Sürükle-bırak: `DragTarget<List<File>>` widget'ı
|
||||
|
||||
**Dosya:** `lib/services/image_manager.dart`
|
||||
|
||||
### Adım 6: Dosya Açma (Dialog + DragDrop)
|
||||
- `file_picker` paketi ile `Ctrl+O` kısayolu
|
||||
- `DragTarget` ile sürükle-bırak
|
||||
- Desteklenen format filtreleri: PNG, JPEG, WebP, BMP, GIF
|
||||
- **Dikkat:** Flutter Linux'ta DragTarget çalışıyor — ayrıca `window_manager`'dan `onDragFile` event'i de var
|
||||
|
||||
**Dosya:** `lib/services/file_handler.dart`
|
||||
|
||||
### Adım 7: Klavye Kısayolları
|
||||
- Flutter'daki `Shortcuts` + `Actions` sistemi
|
||||
- `← →` → resim değiştir
|
||||
- `Ctrl+O` → dosya aç
|
||||
- `F11` → tam ekran (fullscreen toggle)
|
||||
- `Esc` → tam ekrandan çık
|
||||
- `Ctrl+Q` → çıkış
|
||||
|
||||
**Dosya:** `lib/shortcuts/app_shortcuts.dart`
|
||||
|
||||
### Adım 8: Birleştirme ve Test
|
||||
- Ana ekranı `ViewerScreen`'de topla
|
||||
- `Listener(onPointerSignal)` + `InteractiveViewer` entegrasyonu
|
||||
- `flutter run -d linux` ile test
|
||||
- Performance profiling: `flutter run --profile`
|
||||
|
||||
### Adım 9: Derleme
|
||||
- `flutter build linux --release`
|
||||
- Binary: `build/linux/x64/release/bundle/imajViewer`
|
||||
|
||||
## 5. pubspec.yaml Bağımlılıkları
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
window_manager: ^0.4.3
|
||||
file_picker: ^8.0.0
|
||||
path: ^1.9.0
|
||||
```
|
||||
|
||||
## 6. Önemli Dikkat Noktaları
|
||||
|
||||
### Zoom Odağı (Cursor-based Zoom)
|
||||
InteractiveViewer varsayılan zoom odağı merkezdir. İmleç odağında zoom için
|
||||
`TransformationController` ile manuel matrix çarpımı:
|
||||
|
||||
```
|
||||
1. Scroll event yakala (PointerScrollEvent)
|
||||
2. İmlecin resim üzerindeki koordinatını hesapla
|
||||
3. Matrix4.translationValues(-txt) * Matrix4.diagonal3(values(scale)) * Matrix4.translationValues(txt)
|
||||
```
|
||||
|
||||
Detaylı implementasyon `image_canvas.dart`'da yapılacak.
|
||||
|
||||
### Frameless Window Sürükleme
|
||||
Window_manager zaten varsayılan olarak fare ile pencerenin herhangi bir
|
||||
yerinden sürüklenmesine izin vermez. Bunun için:
|
||||
- CustomTitleBar alanını `DragToMoveArea` ile sarmak
|
||||
- Veya `windowManager.startDragging()` çağırmak
|
||||
|
||||
Biz `DragToMoveArea` widget'ını kullanacağız.
|
||||
|
||||
### Performans
|
||||
- Flutter'ın `ImageCache`'i varsayılan olarak 50 MB ve 1000 entry ile sınırlıdır
|
||||
- 12 adet 4K resim için `ImageCache.maximumSizeBytes` 1 GB'a çıkarılmalı
|
||||
- `RepaintBoundary` ile sadece değişen bölgelerin yeniden çizilmesi sağlanır
|
||||
- `Texture` bazlı render ile GPU'da işleme devam eder
|
||||
|
||||
## 7. Timeline
|
||||
|
||||
| Adım | İş | Tahmini Süre |
|
||||
|---|---|---|
|
||||
| 1-2 | Proje iskeleti + window_manager | 15 dk |
|
||||
| 3 | CustomTitleBar | 15 dk |
|
||||
| 4 | ImageCanvas + zoom | 30 dk |
|
||||
| 5-6 | Resim yönetimi + dosya açma | 30 dk |
|
||||
| 7 | Kısayollar | 10 dk |
|
||||
| 8-9 | Birleştirme + build | 20 dk |
|
||||
| **Toplam** | | **~2 saat** |
|
||||
Reference in new issue
Block a user