#181 viewer: fixed "actual size" zoom, allow zooming out small items to actual size, fixed minimap for unsized items

This commit is contained in:
Thibault Deckers 2022-02-19 19:15:49 +09:00
parent d8210ef075
commit 835a2ed18e
9 changed files with 31 additions and 17 deletions

View file

@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
### Added
- optional recycle bin to keep deleted items for 30 days
- Viewer: actions to copy/move to album
- Indonesian translation (thanks MeFinity)
@ -13,6 +14,8 @@ All notable changes to this project will be documented in this file.
- Viewer: action menu reorganization
- Viewer: `Export` action renamed to `Convert`
- Viewer: actual size zoom level respects device pixel ratio
- Viewer: allow zooming out small items to actual size
- Collection: improved performance for sort/group by name
- load previous top items on startup
- upgraded Flutter to stable v2.10.1

View file

@ -378,7 +378,7 @@
"appExportSettings": "Pengaturan",
"settingsSectionNavigation": "Navigasi",
"settingsHome": "Home",
"settingsHome": "Beranda",
"settingsKeepScreenOnTile": "Biarkan layarnya menyala",
"settingsKeepScreenOnTitle": "Biarkan Layarnya Menyala",
"settingsDoubleBackExit": "Ketuk “kembali” dua kali untuk keluar",

View file

@ -71,6 +71,7 @@ class MagnifierController {
position = position ?? this.position;
scale = scale ?? this.scale;
if (this.position == position && this.scale == scale) return;
assert((scale ?? 0) >= 0);
previousState = currentState;
_setState(MagnifierState(
@ -127,7 +128,7 @@ class MagnifierController {
case ScaleState.covering:
return _clamp(ScaleLevel.scaleForCovering(scaleBoundaries.viewportSize, scaleBoundaries.childSize));
case ScaleState.originalSize:
return _clamp(1.0);
return _clamp(scaleBoundaries.originalScale);
default:
return null;
}

View file

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:aves/widgets/common/magnifier/controller/controller.dart';
import 'package:aves/widgets/common/magnifier/controller/controller_delegate.dart';
import 'package:aves/widgets/common/magnifier/controller/state.dart';
@ -132,7 +134,7 @@ class _MagnifierCoreState extends State<MagnifierCore> with TickerProviderStateM
updateScaleStateFromNewScale(newScale, ChangeSource.gesture);
updateMultiple(
scale: newScale,
scale: max(0, newScale),
position: newPosition,
source: ChangeSource.gesture,
);

View file

@ -1,3 +1,4 @@
import 'dart:math';
import 'dart:ui';
import 'package:aves/widgets/common/magnifier/controller/controller.dart';
@ -41,11 +42,13 @@ class ScaleBoundaries extends Equatable {
}
}
double get minScale => _scaleForLevel(_minScale);
double get originalScale => 1.0 / window.devicePixelRatio;
double get maxScale => _scaleForLevel(_maxScale).clamp(minScale, double.infinity);
double get minScale => {_scaleForLevel(_minScale), originalScale, initialScale}.fold(double.infinity, min);
double get initialScale => _scaleForLevel(_initialScale).clamp(minScale, maxScale);
double get maxScale => {_scaleForLevel(_maxScale), originalScale, initialScale}.fold(0, max);
double get initialScale => _scaleForLevel(_initialScale);
Offset get _viewportCenter => viewportSize.center(Offset.zero);

View file

@ -35,7 +35,7 @@ class DecoratedThumbnail extends StatelessWidget {
);
child = Stack(
alignment: AlignmentDirectional.bottomStart,
fit: StackFit.passthrough,
children: [
child,
ThumbnailEntryOverlay(entry: entry),

View file

@ -38,11 +38,13 @@ class ThumbnailEntryOverlay extends StatelessWidget {
if (entry.trashed && context.select<GridThemeData, bool>((t) => t.showTrash)) TrashIcon(trashDaysLeft: entry.trashDaysLeft),
];
if (children.isEmpty) return const SizedBox();
if (children.length == 1) return children.first;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: children,
return Align(
alignment: AlignmentDirectional.bottomStart,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: children,
),
);
}
}

View file

@ -78,6 +78,8 @@ class MinimapPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
if (entrySize.width <= 0 || entrySize.height <= 0) return;
final viewSize = entrySize * viewScale;
if (viewSize.isEmpty) return;

View file

@ -1,15 +1,16 @@
import 'package:flutter/foundation.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/widgets.dart';
class ViewState {
@immutable
class ViewState extends Equatable {
final Offset position;
final double? scale;
final Size? viewportSize;
static const ViewState zero = ViewState(Offset.zero, 0, null);
const ViewState(this.position, this.scale, this.viewportSize);
@override
String toString() => '$runtimeType#${shortHash(this)}{position=$position, scale=$scale, viewportSize=$viewportSize}';
List<Object?> get props => [position, scale, viewportSize];
const ViewState(this.position, this.scale, this.viewportSize);
}