fix(video): iOS video zoom

This commit is contained in:
edde746
2026-06-01 15:21:41 +02:00
parent 1020188883
commit a425798bae
6 changed files with 63 additions and 12 deletions
+1 -1
View File
@@ -789,7 +789,7 @@
repositoryURL = "https://github.com/edde746/MPVKit";
requirement = {
kind = revision;
revision = 6f711b36920b37d22e81353dda5a7df7965b1a44;
revision = 60266433556169cf5529a81cc603524ed3e4bec1;
};
};
/* End XCRemoteSwiftPackageReference section */
@@ -40,7 +40,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/edde746/MPVKit",
"state" : {
"revision" : "6f711b36920b37d22e81353dda5a7df7965b1a44"
"revision" : "60266433556169cf5529a81cc603524ed3e4bec1"
}
},
{
@@ -40,7 +40,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/edde746/MPVKit",
"state" : {
"revision" : "6f711b36920b37d22e81353dda5a7df7965b1a44"
"revision" : "60266433556169cf5529a81cc603524ed3e4bec1"
}
},
{
+13 -5
View File
@@ -78,14 +78,22 @@ class VideoFilterManager {
Size? get playerSize => _playerSize;
static double videoZoomPropertyForScale(double scale) {
static double normalizeZoomScale(double scale) {
final clamped = scale.clamp(minZoomScale, maxZoomScale).toDouble();
return math.log(clamped) / math.ln2;
final percent = (clamped * 100).round();
if (percent == 100) return 1.0;
return percent / 100;
}
static double videoZoomPropertyForScale(double scale) {
final normalized = normalizeZoomScale(scale);
if (normalized == 1.0) return 0.0;
return math.log(normalized) / math.ln2;
}
double setZoomScale(double scale) {
final next = scale.clamp(minZoomScale, maxZoomScale).toDouble();
if ((_zoomScale - next).abs() < 0.0001) return _zoomScale;
final next = normalizeZoomScale(scale);
if (_zoomScale == next) return _zoomScale;
_zoomScale = next;
updateVideoFilter();
return _zoomScale;
@@ -140,7 +148,7 @@ class VideoFilterManager {
shouldUpdate = true;
}
if (_prePipZoomScale != null) {
_zoomScale = _prePipZoomScale!;
_zoomScale = normalizeZoomScale(_prePipZoomScale!);
_prePipZoomScale = null;
shouldUpdate = true;
}
@@ -215,15 +215,16 @@ class _VideoSettingsSheetState extends State<VideoSettingsSheet> {
super.initState();
_audioSyncOffset = widget.audioSyncOffset;
_subtitleSyncOffset = widget.subtitleSyncOffset;
_zoomScale = widget.videoZoomScale;
_zoomScale = VideoFilterManager.normalizeZoomScale(widget.videoZoomScale);
_loadDebugDvConversionMode();
}
@override
void didUpdateWidget(covariant VideoSettingsSheet oldWidget) {
super.didUpdateWidget(oldWidget);
if ((widget.videoZoomScale - oldWidget.videoZoomScale).abs() > 0.0001) {
_zoomScale = widget.videoZoomScale;
final nextZoomScale = VideoFilterManager.normalizeZoomScale(widget.videoZoomScale);
if (_zoomScale != nextZoomScale) {
_zoomScale = nextZoomScale;
}
}
@@ -392,7 +393,7 @@ class _VideoSettingsSheetState extends State<VideoSettingsSheet> {
String _formatZoomScale(double scale) => '${(scale * 100).round()}%';
void _setZoomScale(double scale) {
final next = scale.clamp(VideoFilterManager.minZoomScale, VideoFilterManager.maxZoomScale).toDouble();
final next = VideoFilterManager.normalizeZoomScale(scale);
setState(() {
_zoomScale = next;
});
@@ -4,6 +4,48 @@ import 'package:plezy/mpv/mpv.dart';
import 'package:plezy/services/video_filter_manager.dart';
void main() {
test('zoom scale snaps to whole percentages', () {
final player = _RecordingPlayer();
final manager = VideoFilterManager(player: player, availableVersions: const [], selectedMediaIndex: 0);
addTearDown(manager.dispose);
expect(manager.setZoomScale(1.234), 1.23);
expect(manager.zoomScale, 1.23);
expect(manager.adjustZoom(VideoFilterManager.zoomStep), 1.24);
expect(manager.zoomScale, 1.24);
});
test('zoom scale snaps near 100 percent to exact default', () {
final player = _RecordingPlayer();
final manager = VideoFilterManager(player: player, availableVersions: const [], selectedMediaIndex: 0);
addTearDown(manager.dispose);
manager.setZoomScale(1.5);
expect(manager.setZoomScale(1.00008), 1.0);
expect(manager.zoomScale, 1.0);
expect(manager.resetZoom(), 1.0);
});
test('video zoom property is exact zero at normalized default', () async {
final player = _RecordingPlayer();
final manager = VideoFilterManager(player: player, availableVersions: const [], selectedMediaIndex: 0);
addTearDown(manager.dispose);
expect(VideoFilterManager.videoZoomPropertyForScale(1.00008), 0.0);
manager.setZoomScale(1.00008);
await Future<void>.delayed(Duration.zero);
player.writes.clear();
await manager.updateVideoFilter();
final zoomWrites = player.writes.where((write) => write.key == 'video-zoom').toList();
expect(zoomWrites, isNotEmpty);
expect(zoomWrites.last.value, '0.0');
});
test('stretch mode applies the initial player size before a resize event', () async {
final player = _RecordingPlayer();
final manager = VideoFilterManager(