fix: right-button double click no longer wipes rotation mid-drag (v1.7.2)
Two rotate drags started quickly at nearly the same spot were treated as a double click: the reset was detected on button down against the previous down time/position, so it wiped all effects and ignored the second drag, leaving Ctrl+S to save an unrotated crop. - Double click is now only counted for actual clicks (movement <= 4px) and is decided on button up; a drag breaks the chain. - Pointer up is matched by pointer id, so a left-drag pan never counts as a click. - dist: 1.7.2 .deb replaces the tracked 1.7.1 package.
This commit is contained in:
1 parent
32fb12c210
commit
3b1fad18fa
6 files changed
+48
-20
No files matched your search
+1
-1
@@ -49,7 +49,7 @@ app.*.map.json
|
||||
*.deb
|
||||
*.tar.gz
|
||||
*.exe
|
||||
!dist/imajviewer_1.7.1_amd64.deb
|
||||
!dist/imajviewer_1.7.2_amd64.deb
|
||||
!dist/imajviewer_setup_1.1.0.exe
|
||||
deb/usr/lib/imajviewer/
|
||||
release/
|
||||
|
||||
@@ -4,6 +4,17 @@ All notable changes to imajViewer are documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.7.2] - 2026-10-25
|
||||
|
||||
### Fixed
|
||||
- Rotating sometimes vanished before saving: the right-button double-click reset was
|
||||
detected on button *down* against the previous down time and position, so two rotate
|
||||
drags started quickly at nearly the same spot were treated as a double click — all
|
||||
effects (rotation included) were wiped and the second drag was ignored, so `Ctrl+S`
|
||||
saved an unrotated crop. A double click is now only counted for actual clicks
|
||||
(movement ≤ 4 px, decided on button up), a drag breaks the chain, and
|
||||
`pointer up` is matched by pointer id so a left-drag pan never counts as a click.
|
||||
|
||||
## [1.7.1] - 2026-10-25
|
||||
|
||||
### Added
|
||||
|
||||
Binary file not shown.
@@ -17,7 +17,7 @@ import '../shortcuts/app_shortcuts.dart';
|
||||
import '../services/window_persistence.dart';
|
||||
import '../l10n/app_localizations.dart';
|
||||
|
||||
const appVersion = '1.7.1';
|
||||
const appVersion = '1.7.2';
|
||||
|
||||
class ViewerScreen extends StatefulWidget {
|
||||
final List<String> initialFiles;
|
||||
|
||||
@@ -41,6 +41,11 @@ class ImageCanvasState extends State<ImageCanvas> {
|
||||
double _startBrightness = 0;
|
||||
DateTime? _lastRightTapTime;
|
||||
Offset _lastRightTapPos = Offset.zero;
|
||||
/// Sağ tuş basılıyken anlamlı hareket oldu mu? (tıklama mı sürükleme mi)
|
||||
bool _rightDragMoved = false;
|
||||
int? _rightPointerId;
|
||||
/// Sürükleme sayılma eşiği (px) — rotate/contrast ince ayarında el titremesi.
|
||||
static const double _dragClickSlop = 4;
|
||||
|
||||
// ── Klavye modifier tracking ──
|
||||
bool _ctrlPressed = false;
|
||||
@@ -311,23 +316,8 @@ class ImageCanvasState extends State<ImageCanvas> {
|
||||
if (e.buttons != kSecondaryMouseButton) return;
|
||||
|
||||
_pointerDownPos = e.localPosition;
|
||||
|
||||
final now = DateTime.now();
|
||||
if (_lastRightTapTime != null &&
|
||||
now.difference(_lastRightTapTime!) < const Duration(milliseconds: 400) &&
|
||||
(e.localPosition - _lastRightTapPos).distance < 20) {
|
||||
_angle = 0;
|
||||
_contrast = 1.0;
|
||||
_saturation = 1.0;
|
||||
_brightness = 0;
|
||||
_flipH = false;
|
||||
_interactionMode = 'none';
|
||||
_markRenderDirty();
|
||||
_lastRightTapTime = null;
|
||||
return;
|
||||
}
|
||||
_lastRightTapTime = now;
|
||||
_lastRightTapPos = e.localPosition;
|
||||
_rightDragMoved = false;
|
||||
_rightPointerId = e.pointer;
|
||||
|
||||
if (_ctrlPressed && _shiftPressed) {
|
||||
_interactionMode = 'brightness';
|
||||
@@ -346,6 +336,10 @@ class ImageCanvasState extends State<ImageCanvas> {
|
||||
|
||||
void _onPointerMove(PointerMoveEvent e) {
|
||||
if (e.buttons != kSecondaryMouseButton) return;
|
||||
if (!_rightDragMoved &&
|
||||
(e.localPosition - _pointerDownPos).distance > _dragClickSlop) {
|
||||
_rightDragMoved = true;
|
||||
}
|
||||
|
||||
final dy = e.localPosition.dy - _pointerDownPos.dy;
|
||||
|
||||
@@ -367,7 +361,30 @@ class ImageCanvasState extends State<ImageCanvas> {
|
||||
}
|
||||
|
||||
void _onPointerUp(PointerUpEvent e) {
|
||||
if (e.pointer != _rightPointerId) return;
|
||||
_rightPointerId = null;
|
||||
_interactionMode = 'none';
|
||||
// Sürükleme ile biten etkileşim sağ çift tık zincirini keser; yalnızca
|
||||
// gerçek tıklamalar (hareketsiz bas-bırak) çift tık sayılır.
|
||||
if (_rightDragMoved) {
|
||||
_lastRightTapTime = null;
|
||||
_rightDragMoved = false;
|
||||
return;
|
||||
}
|
||||
final now = DateTime.now();
|
||||
final isDouble = _lastRightTapTime != null &&
|
||||
now.difference(_lastRightTapTime!) < const Duration(milliseconds: 400) &&
|
||||
(e.localPosition - _lastRightTapPos).distance < 20;
|
||||
_lastRightTapTime = isDouble ? null : now;
|
||||
_lastRightTapPos = e.localPosition;
|
||||
if (isDouble) {
|
||||
_angle = 0;
|
||||
_contrast = 1.0;
|
||||
_saturation = 1.0;
|
||||
_brightness = 0;
|
||||
_flipH = false;
|
||||
_markRenderDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// ── Combined color filter (brightness × saturation × contrast) ──
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
name: imajviewer
|
||||
description: "Ultra-lightweight image viewer for Linux and Windows."
|
||||
publish_to: 'none'
|
||||
version: 1.7.1+17
|
||||
version: 1.7.2+18
|
||||
|
||||
msix_config:
|
||||
display_name: ImajViewer
|
||||
|
||||
Reference in new issue
Block a user