feat: jfif/jpe/wbmp format destegi, pencere cascade yerlesimi, konum kaydi duzeltmesi
- file_handler/image_manager: jfif, jpe, wbmp uzantilari - .desktop + install.sh MimeType: image/vnd.wap.wbmp eklendi - main.dart: yeni pencere oncekinin saginda acilir (screen_retriever ile ekran tespiti) - viewer_screen: 2sn polling kaldirildi, konum kaydi tek akisa oturtuldu (acilis + move/resize debounce + close senkron) - dist/rebuild-deb.sh: .desktop kaynaktan kopyalanir (MimeType/StartupWMClass guncel kalir) - .deb guncellendi, docs: session-2026-08-03 + plan dokumanlari
This commit is contained in:
59
docs/format-destegi-ek-formatlar.md
Normal file
59
docs/format-destegi-ek-formatlar.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Ek Görüntü Formatları Destek Planı
|
||||
|
||||
> Tarih: 2026-08-03 · Değerlendirme + implementasyon planı
|
||||
> Not: TIFF değerlendirildi ve **vazgeçildi** (kullanıcı kararı). Bu plan yalnızca mevcut mimariye sıfır maliyetle eklenebilen formatları kapsar.
|
||||
|
||||
## 1. Hedef
|
||||
|
||||
imajViewer'ın desteklediği format listesini, **ek decode katmanı gerektirmeden** (Flutter/Skia'nın zaten açabildiği) formatlarla genişletmek.
|
||||
|
||||
## 2. Mevcut Durum
|
||||
|
||||
### Desteklenen uzantılar (kod içi, 3 yerde)
|
||||
| Dosya | Satır | Liste |
|
||||
|---|---|---|
|
||||
| `lib/services/file_handler.dart` | 9 | png, jpg, jpeg, webp, bmp, gif |
|
||||
| `lib/services/image_manager.dart` | 24 | png, jpg, jpeg, webp, bmp, gif |
|
||||
| `imajviewer.desktop` + `deb/.../imajviewer.desktop` | 9 | image/png;image/jpeg;image/webp;image/bmp;image/gif;image/jpg |
|
||||
| `install.sh` | 77 | aynı MimeType listesi |
|
||||
|
||||
### Flutter'ın yerleşik codec'leri (Skia)
|
||||
Resmi dokümantasyona göre Flutter açabilir: **JPEG, PNG, GIF, WebP, BMP, WBMP**
|
||||
|
||||
Yani Skia zaten açabiliyor ama listemizde olmayanlar:
|
||||
- `.jfif` — JPEG/JFIF içerik (aslında JPEG, magic-byte aynı)
|
||||
- `.jpe` — JPEG alternatif uzantısı
|
||||
- `.wbmp` — Skia'da WBMP codec var
|
||||
- `.avif` — **YOK**: Flutter issue #61229 açık, native plugin (`flutter_avif`/libavif) gerekir → kapsam dışı
|
||||
- `.tif/.tiff` — **YOK**: image paketi gerekir → vazgeçildi
|
||||
|
||||
## 3. Eklenecekler
|
||||
|
||||
| Uzantı | MIME | Neden açılır | Maliyet |
|
||||
|---|---|---|---|
|
||||
| `.jfif` | image/jpeg | JPEG codec, aynı magic byte | sadece filtre |
|
||||
| `.jpe` | image/jpeg | JPEG alternatif uzantısı | sadece filtre |
|
||||
| `.wbmp` | image/vnd.wap.wbmp | Skia WBMP codec | sadece filtre |
|
||||
|
||||
> `.avif` bilinçli olarak eklenmiyor: Flutter'ın yerleşik decoder'ı yok; native libavif bağımlılığı "ultra hafif" felsefeyi bozar. İstenirse ileride ayrı plan yapılır.
|
||||
|
||||
## 4. Yapılacaklar (sıralı)
|
||||
|
||||
1. [ ] `file_handler.dart` → allowedExtensions: `'jfif', 'jpe', 'wbmp'` ekle
|
||||
2. [ ] `image_manager.dart` → supported: `'jfif', 'jpe', 'wbmp'` ekle
|
||||
3. [ ] `imajviewer.desktop` → MimeType'a `image/jpeg` zaten var (jfif/jpe kapsar), `image/vnd.wap.wbmp;` ekle
|
||||
4. [ ] `deb/usr/share/applications/imajviewer.desktop` → aynı
|
||||
5. [ ] `install.sh` → aynı MimeType güncellemesi
|
||||
6. [ ] Windows installer (`.iss`) dosya ilişkilendirme listesi kontrolü — varsa `image/jpeg` jfif/jpe'yi kapsar
|
||||
|
||||
## 5. Riskler / Açık Sorular
|
||||
|
||||
- **JFIF varyantı:** Bazı .jfif dosyaları CMYK-JPEG olabilir; Skia çoğunu açıyor ama tamamını değil → açılmayanlar `errorBuilder` ekranı gösterir (mevcut davranış, çökme yok)
|
||||
- **WBMP nadir:** Çoğu kullanıcı hiç karşılaşmaz; eklemesi zararsız
|
||||
- **Windows ilişkilendirme:** Inno Setup `.iss` dosyası `image/jpeg` kayıtlıysa .jfif/.jpe otomatik kapsanır; `.wbmp` için ayrı registry gerekebilir (opsiyonel)
|
||||
|
||||
## 6. Kabul Kriterleri
|
||||
|
||||
- [ ] `.jfif`, `.jpe`, `.wbmp` dosyaları dosya seçicide görünür
|
||||
- [ ] JFIF dosyası pan/zoom/filtre ile görüntülenir
|
||||
- [ ] Mevcut PNG/JPEG/WebP/GIF/BMP davranışı değişmez
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
| Tarih | Dosya | Konu |
|
||||
|---|---|---|
|
||||
| 2026-08-03 | [session-2026-08-03.md](session-2026-08-03.md) | **Session özeti** — jfif/jpe/wbmp, pencere cascade, konum kaydı düzeltmesi |
|
||||
| 2026-08-03 | [format-destegi-ek-formatlar.md](format-destegi-ek-formatlar.md) | **Plan** — jfif/jpe/wbmp desteği (TIFF vazgeçildi) |
|
||||
| 2026-08-03 | [pencere-cascade-yerlesim.md](pencere-cascade-yerlesim.md) | **Plan** — yeni pencereyi yan yana / alt satıra açma (screen_retriever) |
|
||||
| 2026-07-27 | [session-windows-ci.md](session-windows-ci.md) | **Windows setup.exe yeniden derlendi, Gitea CI eklendi** |
|
||||
| 2026-07-27 | [session-2026-07-27.md](session-2026-07-27.md) | **Session özeti** — rotate aktif, StartupWMClass ile taskbar gruplama |
|
||||
| 2026-07-27 | [image-canvas-interactions.md](image-canvas-interactions.md) | Detaylı analiz: contrast, saturation, rotate implementasyon planı |
|
||||
|
||||
111
docs/pencere-cascade-yerlesim.md
Normal file
111
docs/pencere-cascade-yerlesim.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Pencere Cascade Yerleşimi Planı
|
||||
|
||||
> Tarih: 2026-08-03 · Değerlendirme + implementasyon planı (henüz kod değişikliği yapılmadı)
|
||||
|
||||
## 1. Sorun
|
||||
|
||||
imajViewer'a yeni bir resim açıldığında pencere **hep aynı koordinat ve boyutta** açılıyor (önceki pencerenin üstüne biniyor). İstenen davranış:
|
||||
|
||||
- Yeni pencere, önceki pencerenin **x + width** kadar sağına açılsın (yan yana)
|
||||
- Ekrandan **taşacaksa** alt satıra, satır başından (x baştan) açılsın
|
||||
|
||||
Bu, Windows'un klasik "cascade windows" davranışının basit hali.
|
||||
|
||||
## 2. Mevcut Durum Analizi
|
||||
|
||||
### Pencere açılış akışı (`lib/main.dart`)
|
||||
```
|
||||
main(args)
|
||||
→ WindowPersistence.restore() // window.json'dan son konum/boyut
|
||||
→ windowOptions = WindowOptions(size: saved ?? 1280x800)
|
||||
→ waitUntilReadyToShow:
|
||||
saved varsa → setPosition(saved.position) + setSize(saved.size)
|
||||
saved yoksa → center()
|
||||
→ runApp(ImajViewerApp(initialFiles: args))
|
||||
```
|
||||
|
||||
### Konum kaydetme akışı (`lib/screens/viewer_screen.dart` + `lib/services/window_persistence.dart`)
|
||||
- `_startPolling()`: 2 saniyede bir `windowManager.getBounds()` → `WindowPersistence.saveSync()` → `~/.config/imajviewer/window.json` (Linux) / `%APPDATA%/imajviewer/window.json` (Windows)
|
||||
- `onWindowEvent` (move/resize/close) → debounce'lu `_doSave()`
|
||||
|
||||
### Sorunun kökü
|
||||
- Her yeni pencere `window.json`'daki **son kaydedilen** konumu okuyor → aynı yere açılıyor
|
||||
- Cascade mantığı yok; ekran genişliği bilgisi hiç sorgulanmıyor
|
||||
|
||||
## 3. Teknik Araştırma (doğrulandı)
|
||||
|
||||
### window_manager 0.4.3 (mevcut bağımlılık)
|
||||
- `setPosition`, `setSize`, `getBounds`, `getPosition`, `getSize`, `center()` → var
|
||||
- **Ekran/display API'si → YOK** (getScreen/getPrimaryDisplay yok)
|
||||
|
||||
### window_manager 0.5.2 (güncel)
|
||||
- Ekran API'si yine yok — `screen_retriever`'ı bağımlılık olarak içeriyor ama expose etmiyor
|
||||
|
||||
### screen_retriever 0.2.2 (pub.dev, window_manager'ın zaten bağımlısı)
|
||||
- `ScreenRetriever.instance.getPrimaryDisplay()` → `Display`
|
||||
- `getAllDisplays()` → `List<Display>`
|
||||
- `Display` alanları:
|
||||
- `size` (ekran tam boyutu, logical px)
|
||||
- `visiblePosition` (Offset — çalışma alanı başlangıcı)
|
||||
- `visibleSize` (Size — görev çubuğu hariç çalışma alanı)
|
||||
- `scaleFactor`
|
||||
- Linux (X11) + Windows desteği var
|
||||
|
||||
**Karar: `screen_retriever` doğrudan bağımlılık olarak eklenir** (window_manager sürümü değişmez).
|
||||
|
||||
## 4. Önerilen Algoritma
|
||||
|
||||
`main.dart`'ta, `windowOptions` oluşturulmadan önce:
|
||||
|
||||
```
|
||||
1. saved = WindowPersistence.restore()
|
||||
2. display = await ScreenRetriever.instance.getPrimaryDisplay()
|
||||
workArea = display.visiblePosition + display.visibleSize (yoksa display.size)
|
||||
3. Eğer saved != null:
|
||||
newX = saved.x + saved.width // önceki pencerenin sağına
|
||||
newY = saved.y
|
||||
|
||||
// Yatay taşma → alt satıra, satır başına
|
||||
if (newX + pencereGenişliği > workArea.right):
|
||||
newX = workArea.left
|
||||
newY = saved.y + saved.height
|
||||
|
||||
// Dikey taşma da varsa → en başa sar (0,0)
|
||||
if (newY + pencereYüksekliği > workArea.bottom):
|
||||
newX = workArea.left
|
||||
newY = workArea.top
|
||||
|
||||
position = Offset(newX, newY)
|
||||
4. saved yoksa → center() (mevcut davranış)
|
||||
```
|
||||
|
||||
### Örnek
|
||||
- Ekran 1920×1080, pencere 1280×800, önceki pencere (100, 50)
|
||||
- 1. yeni: (1380, 50) — yan yana ✓
|
||||
- 2. yeni: (100+1280*2 = hesaplanır) → 1380+1280=2660 > 1920 → (0, 850) — alt satır başı ✓
|
||||
|
||||
> Not: `saved` her 2 saniyede bir güncellendiği için "önceki pencere" = en son kaydedilmiş konum. Bu, en son açılan pencerenin konumu olur — istenen davranışla uyumlu.
|
||||
|
||||
## 5. Yapılacaklar (sıralı)
|
||||
|
||||
1. [ ] `pubspec.yaml` → `screen_retriever: ^0.2.2` ekle, `flutter pub get`
|
||||
2. [ ] `lib/main.dart` → cascade hesabı ekle (yeni bir servis fonksiyonuna taşınabilir)
|
||||
3. [ ] `lib/services/window_persistence.dart` → `restore()` dışında, cascade hesabı için yardımcı fonksiyon:
|
||||
- `static Future<Offset?> cascadePosition({required Size windowSize})` (opsiyonel, temizlik için)
|
||||
4. [ ] Ekran boyutu alınamazsa (hata / çoklu monitör) → mevcut davranışa düş (saved veya center)
|
||||
5. [ ] Test: ardışık 3-4 resim aç → yan yana dizilim + taşınca alt satır
|
||||
|
||||
## 6. Riskler / Açık Sorular
|
||||
|
||||
- **Çoklu monitör:** `getPrimaryDisplay` birincil ekranı verir. İmleç hangi ekrandaysa oraya açılsın mı? (başlangıç: primary)
|
||||
- **Pencere kapatılıp yenisi açılırsa:** `window.json` son kapanan pencerenin konumunu tutar; yeni pencere onun yanına açılır — boşluk oluşabilir, kabul edilebilir
|
||||
- **Tam ekran / maximize durumu:** saved boyut maximize ise cascade hesabı yine de eski boyutla yapılır; `window.json` sadece normal durumda yazıldığı için risk düşük
|
||||
- **Pencere ekrandan tamamen dışarıdaysa:** `restore()` zaten `x < -1000 || y < -1000` guard'ı var (window_persistence.dart:44) — yine de sağlamlaştırılabilir
|
||||
|
||||
## 7. Kabul Kriterleri
|
||||
|
||||
- [ ] Ardışık 2 pencere: ikincisi birincinin hemen sağında
|
||||
- [ ] Yatay taşma: yeni pencere alt satıra, satır başından başlar
|
||||
- [ ] İlk açılışta (kayıt yok) pencere yine ortalanır
|
||||
- [ ] Pencere boyutu/konumu kaydetme davranışı bozulmaz
|
||||
- [ ] Linux ve Windows'ta çalışır (screen_retriever her ikisini destekliyor)
|
||||
33
docs/session-2026-08-03.md
Normal file
33
docs/session-2026-08-03.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Session Özeti — 2026-08-03
|
||||
|
||||
## Yapılanlar
|
||||
|
||||
### 1. Ek Görüntü Formatları (jfif / jpe / wbmp)
|
||||
- TIFF değerlendirildi, **vazgeçildi** (kullanıcı kararı — image paketi/decode katmanı istenmedi)
|
||||
- AVIF değerlendirildi, **eklenmedi** (Flutter'da yerleşik decoder yok — native libavif gerekir, "ultra hafif" felsefeye aykırı)
|
||||
- Eklendi: `.jfif`, `.jpe` (JPEG içerikli, Skia zaten açıyor), `.wbmp` (Skia WBMP codec)
|
||||
- Değişen yerler: file_handler (seçici), image_manager (filtre), 2× .desktop + install.sh (MimeType)
|
||||
|
||||
### 2. Pencere Cascade Yerleşimi
|
||||
- Yeni pencere artık öncekinin **x + width** kadar sağında açılıyor
|
||||
- Ekrandan taşarsa → alt satıra, satır başından
|
||||
- O da taşarsa → ekran sol-üst köşesine
|
||||
- Ekran bilgisi: `screen_retriever` paketi (window_manager'ın zaten transitive bağımlısıydı, doğrudan bağımlılık yapıldı)
|
||||
- Yeni: `WindowPersistence.cascadePosition()` — getPrimaryDisplay → visibleSize/visiblePosition
|
||||
|
||||
### 3. Pencere Konum Kaydı Düzeltmesi (kök neden)
|
||||
- **Sorun:** Konum kaydedilemiyordu → çözüm olarak 5 yere kayıt koyulmuştu (initState + 2sn polling + move/resize debounce + close + main). Birden fazla pencere açıkken polling konum yarışı yaratıyordu → yeni pencere eski konuma göre hesaplanıp üstüne düşüyordu.
|
||||
- **Çözüm:** Polling kaldırıldı. Tek akış:
|
||||
1. `main.dart` — pencere açılışında konum anında saveSync (sıradaki pencere güncel referans okur)
|
||||
2. `viewer_screen` move/resize — son bilinen bounds hemen `_lastBounds`'a, 300ms debounce ile saveSync
|
||||
3. `viewer_screen` close — `_lastBounds` **senkron** saveSync (async çağrı kapanışta tamamlanmıyordu)
|
||||
|
||||
## Doğrulama
|
||||
- `flutter analyze` — 18 info uyarı (mevcut kod stil/deprecated), hata yok
|
||||
- `flutter build linux --release` ✓
|
||||
- Kurulum: release bundle `~/.local/lib/imajviewer/` (install.sh debug bundle'ı önceliklendirdiği için elle kopyalandı)
|
||||
- Kullanıcı manuel test: WebP açılıyor ✓, cascade düzgün çalışıyor ✓
|
||||
|
||||
## Not
|
||||
- `docs/session-windows-ci.md` bozuk encoding (mojibake) — içerik git log'dan biliniyor, düzeltilmedi
|
||||
- Windows setup.exe **yeniden derlenmedi** — sadece Linux build + .deb güncellendi (Windows CI zaten Gitea Actions'ta)
|
||||
Reference in New Issue
Block a user