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:
@@ -25,7 +25,11 @@ void main(List<String> args) async {
|
||||
|
||||
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
if (saved != null) {
|
||||
await windowManager.setPosition(saved.position);
|
||||
final position = await WindowPersistence.cascadePosition(
|
||||
previousPosition: saved.position,
|
||||
previousSize: saved.size,
|
||||
);
|
||||
await windowManager.setPosition(position);
|
||||
await windowManager.setSize(saved.size);
|
||||
} else {
|
||||
await windowManager.center();
|
||||
@@ -33,6 +37,11 @@ void main(List<String> args) async {
|
||||
await windowManager.setResizable(true);
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
|
||||
// Açılış konumunu hemen kaydet — sıradaki pencere güncel referans okusun
|
||||
final pos = await windowManager.getPosition();
|
||||
final size = await windowManager.getSize();
|
||||
WindowPersistence.saveSync(position: pos, size: size);
|
||||
});
|
||||
|
||||
// Extract file paths from command-line arguments
|
||||
|
||||
@@ -21,7 +21,6 @@ class _ViewerScreenState extends State<ViewerScreen> with WindowListener {
|
||||
bool _hasImages = false;
|
||||
bool _isDragging = false;
|
||||
Timer? _saveDebounce;
|
||||
Timer? _pollTimer;
|
||||
Rect _lastBounds = Rect.zero;
|
||||
|
||||
@override
|
||||
@@ -35,29 +34,6 @@ class _ViewerScreenState extends State<ViewerScreen> with WindowListener {
|
||||
FileHandler.loadImagesFromPaths(widget.initialFiles);
|
||||
});
|
||||
}
|
||||
|
||||
// İlk kayıt + periyodik polling başlat
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
await _doSave();
|
||||
_startPolling();
|
||||
});
|
||||
}
|
||||
|
||||
void _startPolling() {
|
||||
_pollTimer?.cancel();
|
||||
_pollTimer = Timer.periodic(const Duration(seconds: 2), (_) async {
|
||||
try {
|
||||
final bounds = await windowManager.getBounds();
|
||||
if (bounds != _lastBounds) {
|
||||
_lastBounds = bounds;
|
||||
WindowPersistence.saveSync(
|
||||
position: bounds.topLeft,
|
||||
size: bounds.size,
|
||||
);
|
||||
}
|
||||
} catch (_) {}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -65,7 +41,6 @@ class _ViewerScreenState extends State<ViewerScreen> with WindowListener {
|
||||
windowManager.removeListener(this);
|
||||
ImageManager.instance.removeListener(_onImageManagerChanged);
|
||||
_saveDebounce?.cancel();
|
||||
_pollTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -74,10 +49,18 @@ class _ViewerScreenState extends State<ViewerScreen> with WindowListener {
|
||||
void onWindowEvent(String eventName) {
|
||||
switch (eventName) {
|
||||
case 'close':
|
||||
_doSave();
|
||||
// Senkron kayıt — async çağrı kapanışta tamamlanmayabilir
|
||||
if (_lastBounds != Rect.zero) {
|
||||
WindowPersistence.saveSync(
|
||||
position: _lastBounds.topLeft,
|
||||
size: _lastBounds.size,
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'resize':
|
||||
case 'move':
|
||||
// Son bilinen konumu hemen güncelle (kapanış senkron kaydı için)
|
||||
windowManager.getBounds().then((b) => _lastBounds = b).catchError((_) {});
|
||||
_saveDebounce?.cancel();
|
||||
_saveDebounce = Timer(const Duration(milliseconds: 300), () {
|
||||
_doSave();
|
||||
|
||||
@@ -6,7 +6,7 @@ class FileHandler {
|
||||
static Future<void> openFileDialog() async {
|
||||
final result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ['png', 'jpg', 'jpeg', 'webp', 'bmp', 'gif'],
|
||||
allowedExtensions: ['png', 'jpg', 'jpeg', 'jfif', 'jpe', 'webp', 'bmp', 'gif', 'wbmp'],
|
||||
allowMultiple: true,
|
||||
);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class ImageManager extends ChangeNotifier {
|
||||
void addImages(List<String> paths) {
|
||||
final validPaths = paths.where((p) {
|
||||
final ext = p.toLowerCase().split('.').last;
|
||||
const supported = ['png', 'jpg', 'jpeg', 'webp', 'bmp', 'gif'];
|
||||
const supported = ['png', 'jpg', 'jpeg', 'jfif', 'jpe', 'webp', 'bmp', 'gif', 'wbmp'];
|
||||
return supported.contains(ext) && File(p).existsSync();
|
||||
}).toList();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:screen_retriever/screen_retriever.dart';
|
||||
|
||||
/// Persists and restores window position and size.
|
||||
class WindowPersistence {
|
||||
@@ -51,4 +52,38 @@ class WindowPersistence {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Cascade: place new window to the right of the previous one.
|
||||
/// Falls to the next row (row start) when it would overflow the screen,
|
||||
/// and wraps to the top-left if the next row also overflows.
|
||||
static Future<Offset> cascadePosition({
|
||||
required Offset previousPosition,
|
||||
required Size previousSize,
|
||||
}) async {
|
||||
try {
|
||||
final display = await screenRetriever.getPrimaryDisplay();
|
||||
final workLeft = display.visiblePosition?.dx ?? 0;
|
||||
final workTop = display.visiblePosition?.dy ?? 0;
|
||||
final workWidth = display.visibleSize?.width ?? display.size.width;
|
||||
final workHeight = display.visibleSize?.height ?? display.size.height;
|
||||
|
||||
var x = previousPosition.dx + previousSize.width;
|
||||
var y = previousPosition.dy;
|
||||
|
||||
if (x + previousSize.width > workLeft + workWidth) {
|
||||
x = workLeft;
|
||||
y = previousPosition.dy + previousSize.height;
|
||||
}
|
||||
|
||||
if (y + previousSize.height > workTop + workHeight) {
|
||||
x = workLeft;
|
||||
y = workTop;
|
||||
}
|
||||
|
||||
return Offset(x, y);
|
||||
} catch (_) {
|
||||
// Fallback: keep previous position if screen info is unavailable.
|
||||
return previousPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user