#181 viewer: fixed "actual size" zoom, allow zooming out small items to actual size, fixed minimap for unsized items
This commit is contained in:
parent
d8210ef075
commit
835a2ed18e
9 changed files with 31 additions and 17 deletions
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class DecoratedThumbnail extends StatelessWidget {
|
|||
);
|
||||
|
||||
child = Stack(
|
||||
alignment: AlignmentDirectional.bottomStart,
|
||||
fit: StackFit.passthrough,
|
||||
children: [
|
||||
child,
|
||||
ThumbnailEntryOverlay(entry: entry),
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue