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
|
*.deb
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.exe
|
*.exe
|
||||||
!dist/imajviewer_1.7.1_amd64.deb
|
!dist/imajviewer_1.7.2_amd64.deb
|
||||||
!dist/imajviewer_setup_1.1.0.exe
|
!dist/imajviewer_setup_1.1.0.exe
|
||||||
deb/usr/lib/imajviewer/
|
deb/usr/lib/imajviewer/
|
||||||
release/
|
release/
|
||||||
|
|||||||
@@ -4,6 +4,17 @@ All notable changes to imajViewer are documented in this file.
|
|||||||
|
|
||||||
## [Unreleased]
|
## [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
|
## [1.7.1] - 2026-10-25
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
Binary file not shown.
@@ -17,7 +17,7 @@ import '../shortcuts/app_shortcuts.dart';
|
|||||||
import '../services/window_persistence.dart';
|
import '../services/window_persistence.dart';
|
||||||
import '../l10n/app_localizations.dart';
|
import '../l10n/app_localizations.dart';
|
||||||
|
|
||||||
const appVersion = '1.7.1';
|
const appVersion = '1.7.2';
|
||||||
|
|
||||||
class ViewerScreen extends StatefulWidget {
|
class ViewerScreen extends StatefulWidget {
|
||||||
final List<String> initialFiles;
|
final List<String> initialFiles;
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ class ImageCanvasState extends State<ImageCanvas> {
|
|||||||
double _startBrightness = 0;
|
double _startBrightness = 0;
|
||||||
DateTime? _lastRightTapTime;
|
DateTime? _lastRightTapTime;
|
||||||
Offset _lastRightTapPos = Offset.zero;
|
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 ──
|
// ── Klavye modifier tracking ──
|
||||||
bool _ctrlPressed = false;
|
bool _ctrlPressed = false;
|
||||||
@@ -311,23 +316,8 @@ class ImageCanvasState extends State<ImageCanvas> {
|
|||||||
if (e.buttons != kSecondaryMouseButton) return;
|
if (e.buttons != kSecondaryMouseButton) return;
|
||||||
|
|
||||||
_pointerDownPos = e.localPosition;
|
_pointerDownPos = e.localPosition;
|
||||||
|
_rightDragMoved = false;
|
||||||
final now = DateTime.now();
|
_rightPointerId = e.pointer;
|
||||||
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;
|
|
||||||
|
|
||||||
if (_ctrlPressed && _shiftPressed) {
|
if (_ctrlPressed && _shiftPressed) {
|
||||||
_interactionMode = 'brightness';
|
_interactionMode = 'brightness';
|
||||||
@@ -346,6 +336,10 @@ class ImageCanvasState extends State<ImageCanvas> {
|
|||||||
|
|
||||||
void _onPointerMove(PointerMoveEvent e) {
|
void _onPointerMove(PointerMoveEvent e) {
|
||||||
if (e.buttons != kSecondaryMouseButton) return;
|
if (e.buttons != kSecondaryMouseButton) return;
|
||||||
|
if (!_rightDragMoved &&
|
||||||
|
(e.localPosition - _pointerDownPos).distance > _dragClickSlop) {
|
||||||
|
_rightDragMoved = true;
|
||||||
|
}
|
||||||
|
|
||||||
final dy = e.localPosition.dy - _pointerDownPos.dy;
|
final dy = e.localPosition.dy - _pointerDownPos.dy;
|
||||||
|
|
||||||
@@ -367,7 +361,30 @@ class ImageCanvasState extends State<ImageCanvas> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _onPointerUp(PointerUpEvent e) {
|
void _onPointerUp(PointerUpEvent e) {
|
||||||
|
if (e.pointer != _rightPointerId) return;
|
||||||
|
_rightPointerId = null;
|
||||||
_interactionMode = 'none';
|
_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) ──
|
// ── Combined color filter (brightness × saturation × contrast) ──
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
name: imajviewer
|
name: imajviewer
|
||||||
description: "Ultra-lightweight image viewer for Linux and Windows."
|
description: "Ultra-lightweight image viewer for Linux and Windows."
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 1.7.1+17
|
version: 1.7.2+18
|
||||||
|
|
||||||
msix_config:
|
msix_config:
|
||||||
display_name: ImajViewer
|
display_name: ImajViewer
|
||||||
|
|||||||
Reference in new issue
Block a user