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:
209
docs/Implementation.md
Normal file
209
docs/Implementation.md
Normal file
@@ -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** |
|
||||
100
docs/PRD.md
Normal file
100
docs/PRD.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# PRD — imajViewer
|
||||
|
||||
> Product Requirements Document
|
||||
> Versiyon: 1.0
|
||||
> Tarih: 2026-07-22
|
||||
|
||||
---
|
||||
|
||||
## 1. Ürün Özeti
|
||||
|
||||
**imajViewer**, Flutter ile geliştirilmiş, Linux masaüstünde çalışan ultra hafif bir görüntü izleyici uygulamasıdır.
|
||||
12'den fazla yüksek çözünürlüklü resmi aynı anda açabilir, fare tekerleği ile anlık zoom yapabilir ve
|
||||
tüm pencere alanını resim göstermek için kullanır.
|
||||
|
||||
## 2. Hedef Kitle
|
||||
|
||||
- Linux kullanıcıları
|
||||
- Fotoğrafçılar, tasarımcılar (hızlı önizleme ihtiyacı)
|
||||
- Yüksek sayıda resim arasında hızlıca gezinmek isteyen kullanıcılar
|
||||
|
||||
## 3. Fonksiyonel Gereksinimler
|
||||
|
||||
### F-01: Resim Açma
|
||||
- Kullanıcı dosya yöneticisinden sürükle-bırak ile resim ekleyebilir
|
||||
- Aynı anda 12+ resim açılabilir
|
||||
- Desteklenen formatlar: PNG, JPEG, WebP, BMP, GIF (statik)
|
||||
|
||||
### F-02: Zoom
|
||||
- Fare tekerleği (mouse scroll) ile kademesiz zoom
|
||||
- Zoom odağı fare imlecinin bulunduğu nokta olmalı
|
||||
- Zoom oranı: %10 - %1000 arası
|
||||
|
||||
### F-03: Frameless Pencere
|
||||
- Native title bar yok, sadece sağ üstte küçült (minimize) ve kapat (close) butonları
|
||||
- Pencere sürüklenebilir (üst kısımdan)
|
||||
- Pencere boyutlandırılabilir (kenarlardan/köşelerden)
|
||||
|
||||
### F-04: Görüntüleme
|
||||
- Scroll bar yok
|
||||
- Resim pencereye sığacak şekilde başlangıçta yerleşir (fit)
|
||||
- Siyah/zemin renkli arka plan
|
||||
- Pencere yeniden boyutlandırılınca resim yeniden ortalanır
|
||||
|
||||
### F-05: Navigasyon (ileri versiyon)
|
||||
- Klavye kısayolları (← → ile resim değiştirme)
|
||||
- Alt kısımda thumbnail strip
|
||||
|
||||
## 4. Fonksiyonel Olmayan Gereksinimler
|
||||
|
||||
### NF-01: Performans
|
||||
- 12 adet 4K (3840x2160) resim aynı anda açıkken akıcı zoom (en az 60 FPS)
|
||||
- Bellek kullanımı 2 GB'ı geçmemeli
|
||||
- Resimler GPU'da işlenmeli, CPU yeniden ölçekleme yapılmamalı
|
||||
|
||||
### NF-02: Başlangıç Süresi
|
||||
- Uygulama 2 saniyeden kısa sürede açılmalı
|
||||
|
||||
### NF-03: Binary Boyutu
|
||||
- Derlenmiş uygulama 50 MB'ı geçmemeli
|
||||
|
||||
### NF-04: Güvenilirlik
|
||||
- Büyük resimler (10000x10000 pixel) uygulamayı çökertmemeli
|
||||
- Bellek sınırı aşılınca en eski resim otomatik boşaltılmalı
|
||||
|
||||
## 5. UI Tasarım İlkeleri
|
||||
|
||||
- **Minimalist:** Sadece resim var, gereksiz hiçbir UI öğesi yok
|
||||
- **Karanlık tema:** Siyah (#1a1a1a) zemin
|
||||
- **Frameless:** Hiçbir pencere çerçevesi görünmez
|
||||
- **Duyarlı:** Pencere boyutu değişince resim otomatik yeniden boyutlanır
|
||||
|
||||
## 6. Teknik Yığın
|
||||
|
||||
| Bileşen | Teknoloji |
|
||||
|---|---|
|
||||
| UI Framework | Flutter 3.44+ |
|
||||
| Platform | Linux Desktop (GTK arkaplan) |
|
||||
| Dil | Dart 3.12+ |
|
||||
| Window Yönetimi | window_manager |
|
||||
| State Yönetimi | ValueNotifier / ChangeNotifier |
|
||||
| Resim İşleme | dart:ui Image + ImageCache |
|
||||
| Render | Skia / Impeller (GPU) |
|
||||
|
||||
## 7. Kullanıcı Akışı
|
||||
|
||||
1. Uygulama açılır → boş siyah ekran
|
||||
2. Kullanıcı dosyaları sürükler veya `Ctrl+O` ile açar
|
||||
3. Resim(ler) pencereye sığacak şekilde görüntülenir
|
||||
4. Fare tekerleği → zoom in/out (imleç odağında)
|
||||
5. Fare sürükleme → resmi kaydırma (pan)
|
||||
6. Pencere yeniden boyutlandırma → resim yeniden ortalanır
|
||||
7. Sağ üst X → uygulama kapanır
|
||||
|
||||
## 8. Başarı Kriterleri
|
||||
|
||||
- [ ] 12 adet 4K resim açıkken zoom akıcı (60 FPS)
|
||||
- [ ] Frameless pencere sorunsuz çalışıyor
|
||||
- [ ] Scroll zoom imleç odağında çalışıyor
|
||||
- [ ] Bellek kullanımı 2 GB altında
|
||||
- [ ] Binary boyutu 50 MB altında
|
||||
@@ -1,7 +1,11 @@
|
||||
# imajViewer — Dokümantasyon İndeksi
|
||||
|
||||
| Tarih | Dosya | Konu |
|
||||
|---|---|---|
|
||||
||---|---|---|
|
||||
| 2026-08-06 | [rapor-github-acik-kaynak.md](rapor-github-acik-kaynak.md) | **Rapor** — GitHub açık kaynak hazırlığı (gereksinimler, riskler, plan) |
|
||||
| 2026-08-06 | [Implementation.md](Implementation.md) | Teknik uygulama dokümanı (kökten taşındı) |
|
||||
| 2026-08-06 | [PRD.md](PRD.md) | Product Requirements Document (kökten taşındı) |
|
||||
| 2026-08-06 | [update_plan_01.md](update_plan_01.md) | Pan sınırlama & zoom merkezi sorunu (kökten taşındı) |
|
||||
| 2026-08-06 | [rapor-pan-kilitleme-nuks.md](rapor-pan-kilitleme-nuks.md) | **Rapor** — efekt uygulanmış görselde pan sırasında kilitlenme nüksü (analiz, açık sorular) |
|
||||
| 2026-08-06 | [rapor-gezinme-ayarlar-print.md](rapor-gezinme-ayarlar-print.md) | **Rapor** — gezinme okları (hover), ayarlar/gear (sıralama), yazdırma (printing paketi) |
|
||||
| 2026-08-06 | [rapor-sag-tik-donma-analizi.md](rapor-sag-tik-donma-analizi.md) | **Rapor** — sağ tuş efektlerinde donma analizi + slider UI değerlendirmesi |
|
||||
|
||||
88
docs/rapor-github-acik-kaynak.md
Normal file
88
docs/rapor-github-acik-kaynak.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Rapor — imajViewer'ı GitHub'da Açık Kaynak Yapmak
|
||||
|
||||
> Tarih: 2026-08-06
|
||||
> Konu: GitHub'a açık kaynak repo koymak için gerekenler + mevcut repo durumu + geçmiş/silinme sorusu + "pro" hale getirme planı
|
||||
|
||||
## 1. Sorunun cevabı: dosya silersem GitHub'a eski dosyalar gider mi?
|
||||
|
||||
**Çalışma ağacından gider, geçmişten GİTMEZ.**
|
||||
|
||||
- Aynı repo geçmişini (aynı commit zincirini) GitHub'a push edersen: sildiğin dosyalar
|
||||
son sürümde (en son commit'te) görünmez, ama **git geçmişindeki eski commit'lerde
|
||||
aynen durur**. GitHub'da eski commit'lere tıklayan herkes o dosyaları görür ve indirebilir.
|
||||
- Üstelik bu geçmiş 391 MB binary taşıyor (aşağıda detay). GitHub'a geçmişle gitmek hem
|
||||
bu yükü hem de "eski dosyalar hâlâ orada" sorununu getirir.
|
||||
- **Öneri:** GitHub için geçmişsiz / tek commit'li temiz başlangıç yap. Ya `git init` ile
|
||||
yeni repo (sıfır geçmiş), ya da squash ile tek commit. O zaman ne sildiysen tamamen gider.
|
||||
|
||||
## 2. GitHub'a açık kaynak repo koymak için gerekenler (checklist)
|
||||
|
||||
| Öğe | Durum | Not |
|
||||
|---|---|---|
|
||||
| LICENSE dosyası | ❌ YOK | README'de "MIT" yazıyor ama kökte LICENSE dosyası yok. GitHub lisansı bunu algılamaz |
|
||||
| README | ⚠️ Var | Gitea URL'leri içeriyor, Türkçe, badge yok (detay: madde 4) |
|
||||
| CONTRIBUTING.md | ❌ YOK | Katkı kuralları (kod stili, test, PR süreci) |
|
||||
| CODE_OF_CONDUCT.md | ❌ YOK | GitHub topluluk standartları için beklenir |
|
||||
| SECURITY.md | ❌ YOK | Güvenlik açığı bildirim yolu (private advisory) |
|
||||
| CHANGELOG.md | ❌ YOK | 1.0.0 → 1.1.0 geçmişi yazılı değil |
|
||||
| CI (GitHub Actions) | ❌ YOK | Sadece `.gitea/workflows/` var — GitHub bunu ÇALIŞTIRMAZ, `.github/workflows/` gerekir |
|
||||
| Issue/PR template | ❌ YOK | `.github/ISSUE_TEMPLATE/` + `PULL_REQUEST_TEMPLATE.md` |
|
||||
| .gitignore | ✅ Var | İyi durumda (build/, .dart_tool/ ignore ediliyor) |
|
||||
| Repo metadata | ❌ | description + topics (image-viewer, flutter, linux, windows) + lisans seçimi |
|
||||
| Releases | ⚠️ | v1.1.0 tag + .deb/.exe asset'leri GitHub Releases'e taşınmalı |
|
||||
| FUNDING.yml | ❌ | Opsiyonel |
|
||||
|
||||
## 3. KRİTİK: Sızıntı / hijyen riskleri
|
||||
|
||||
1. **Gömülü token:** `git remote -v` çıktısında origin URL'si
|
||||
`https://git_alhan:1254baa3...@git.softmediadesign.com/...` — token URL'e gömülü.
|
||||
Bu dosya `.git/config`'te; push ile GitHub'a gitmez (config transfer edilmez).
|
||||
Ama GitHub'a yeni remote eklerken bu URL'yi yanlışlıkla kopyalamamaya dikkat.
|
||||
Token'ı Gitea'dan yenilemek en temizi.
|
||||
2. **Kişisel dosyalar repoda:** `imajviewer.desktop` (yerel .desktop, mode 600),
|
||||
`Implementation.md`, `PRD.md`, `update_plan_01.md`, `docs/session-*.md`,
|
||||
`docs/rapor-*.md` — iç geliştirme notları. Açık kaynak repo'da hepsi durmamalı.
|
||||
3. **Binary dosyalar git'te:** `deb/` (16 MB libflutter_linux_gtk.so vb. — build çıktısı)
|
||||
ve `dist/` (.deb, .exe — sürüm paketleri) git ile takip ediliyor. Binary'ler git'e
|
||||
girmez; release asset'i olur. `.gitignore`'da `*.deb`/`*.exe` var ama `!dist/*.deb`
|
||||
istisnası ve `deb/` dizini bunları açıkta bırakıyor.
|
||||
4. **Mutlak yol:** `pubspec.yaml` → `msix_config.logo_path: C:/projects/imajviewer/...`
|
||||
— yerel Windows yolu. GitHub runner'ında msix adımı kırılır; göreli yol olmalı.
|
||||
5. **Geçmiş 391 MB:** En büyük blob'lar: setup.exe 24 MB ×4 kopya, libflutter_linux_gtk.so
|
||||
16 MB, .deb'ler 8-11 MB ×8, tar.gz 9 MB. GitHub'da dosya limiti 100 MB — şu an
|
||||
geçmiyor ama repo 1 GB'a yaklaşırsa GitHub uyarır, şişkinlik de kötü görünür.
|
||||
|
||||
## 4. README düzeltmeleri
|
||||
|
||||
- Klon/curl komutlarındaki `git.softmediadesign.com` URL'leri GitHub URL'si olmalı
|
||||
- `.deb` kurulum adımındaki sürüm `1.0.0` yazılmış, güncel `1.1.0`
|
||||
- Türkçe → açık kaynak için İngilizce (veya TR+EN iki dilli) önerilir
|
||||
- Badge'ler (build status, license, release) + ekran görüntüsü (imajviewer.png var)
|
||||
- "Gitea Actions" bölümü → "GitHub Actions" olarak yeniden yazılmalı
|
||||
|
||||
## 5. "Pro" hale getirme planı (uygulama adımları, onay sonrası)
|
||||
|
||||
1. **Kök temizliği:** `imajviewer.desktop` sil; iç dokümanları (Implementation/PRD/
|
||||
update_plan/docs) taşı ya da sil — karar gerekiyor (aşağıda).
|
||||
2. **Binary'leri git'ten çıkar:** `git rm --cached deb/ dist/*.deb dist/*.exe`,
|
||||
`.gitignore`'u düzelt (deb/ tamamen ignore; dist/'te sadece rebuild-deb.sh kalsın).
|
||||
Not: `git rm --cached` sadece ileriye dönük temizler; geçmişteki 391 MB durur —
|
||||
tam temizlik için ya filter-repo ya da temiz başlangıç gerekir.
|
||||
3. **Lisans:** Köke `LICENSE` (MIT) ekle.
|
||||
4. **README'yi yeniden yaz:** İngilizce, GitHub linkleri, badge, screenshot.
|
||||
5. **Topluluk dosyaları:** CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md,
|
||||
CHANGELOG.md, `.github/` (issue/PR template + workflows/build-windows.yml).
|
||||
6. **CI'ı GitHub'a uyarla:** `.gitea/workflows/build-windows.yml` → `.github/workflows/`:
|
||||
`GITEA_TOKEN` → `GITHUB_TOKEN` (otomatik), release adımı
|
||||
`softprops/action-gh-release` ile GitHub Release + .deb/.exe asset.
|
||||
7. **pubspec.yaml:** `logo_path`'i göreli yap (CI'da msix kırılmasın).
|
||||
8. **GitHub'a aktarım:** Yeni boş GitHub repo → `git remote add github <url>` →
|
||||
temiz tek commit (squash/orphan) → `git push github main`. Gitea ayrı kalır.
|
||||
|
||||
## 6. Açık kararlar (senin onayın gerekiyor)
|
||||
|
||||
1. README dili: İngilizce mi, TR mi, iki dilli mi? (açık kaynak görünürlüğü için İngilizce önerilir)
|
||||
2. `docs/` ve kök dokümanlar: iç raporlar/session notları ne olacak? (yerel yedek alınır mı?)
|
||||
3. Geçmiş: temiz tek commit mi, yoksa tüm geçmiş GitHub'a taşınsın mı? (öneri: temiz tek commit)
|
||||
4. GitHub hesabı/org: repo hangi hesaba? Repo adı: `imajviewer` mi `imajViewer` mi?
|
||||
5. Lisans: MIT kesin mi? (README'de MIT yazıyor, dosya yok)
|
||||
45
docs/update_plan_01.md
Normal file
45
docs/update_plan_01.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# ImajViewer — Pan Sınırlama & Zoom Merkezi Sorunu ✅ ÇÖZÜLDÜ
|
||||
|
||||
> **Tarih:** 2026-07-23
|
||||
> **Dosya:** `lib/widgets/image_canvas.dart`
|
||||
> **Durum:** ✅ Çözüldü
|
||||
|
||||
---
|
||||
|
||||
## Nihai Çözüm
|
||||
|
||||
### 1. Zoom — `Matrix4.copy(m)..translate..scale..translate`
|
||||
Cursor merkezli zoomAroundPoint. Hem fill hem fit modunda çalışır çünkü `localPosition` her zaman Listener'a göre doğru koordinat verir. `_currentScale` listener'da güncellenir.
|
||||
|
||||
### 2. `_clampAfterZoom` — Image offset + sadece boundary clamp
|
||||
**Kritik:** Fit modunda (BoxFit.contain) Image, Center widget içinde **ortalanır**. Offset hesaplanarak image'ın viewport'taki gerçek sınırları bulunur:
|
||||
|
||||
```dart
|
||||
imgOffsetX = (viewportW - imageW) / 2 // fill modunda 0, fit modunda >0
|
||||
imgLeft = tx + imgOffsetX * scale
|
||||
imgRight = tx + (imgOffsetX + imageW) * scale
|
||||
```
|
||||
|
||||
**SADECE** image viewport'tan büyükse clamp yapılır. Küçükse **dokunulmaz** — zoom-around-point merkezi korunur. Kullanıcı double-tap ile istediği zaman ortalamayı sıfırlayabilir (`Matrix4.identity()`).
|
||||
|
||||
### 3. `translate` — asla `setTranslationRaw` kullanma
|
||||
`setTranslationRaw` matrisin translation sütununu ezer → zoom merkezini bozar. `translate(dx,dy)` ekleme yapar → zoom merkezi korunur.
|
||||
|
||||
### 4. Listener'da clamp YOK
|
||||
Sadece `_currentScale` takip edilir. Pan → `boundaryMargin: EdgeInsets.zero`, Zoom → `_handleScroll` içinde `_clampAfterZoom`.
|
||||
|
||||
---
|
||||
|
||||
## Akış
|
||||
|
||||
```
|
||||
Scroll → _handleScroll → zoomAroundPoint → _controller.value
|
||||
↓
|
||||
_clampAfterZoom()
|
||||
├─ image > viewport → translate ile clamp
|
||||
└─ image ≤ viewport → dokunma
|
||||
|
||||
Pan → InteractiveViewer → _controller.value (boundaryMargin sınırlar)
|
||||
↓
|
||||
_onTransformChanged → sadece _currentScale
|
||||
```
|
||||
Reference in New Issue
Block a user