fix(tvOS): route dpad clicks through engine

This commit is contained in:
edde746
2026-05-11 18:08:56 +02:00
parent 0775ea0d26
commit 9085d4d94b
9 changed files with 142 additions and 91 deletions
+11 -8
View File
@@ -5,19 +5,22 @@ import 'package:flutter/services.dart';
extension KeyEventActionable on KeyEvent {
bool get isActionable => this is KeyDownEvent || this is KeyRepeatEvent;
bool get isPhysicalKeyboardEvent => deviceType == ui.KeyEventDeviceType.keyboard;
// Only true keyboard submit keys belong here. LogicalKeyboardKey.select is
// a TV-remote / dpad-center key (Android DPAD_CENTER, tvOS UIPressTypeSelect)
// — USB keyboards never emit it. The custom Flutter tvOS engine reports its
// synthesized Siri Remote presses with deviceType=keyboard, so classifying
// select-with-keyboard-deviceType as a "keyboard enter" would route center
// dpad through TextField submit and skip the TV virtual keyboard.
bool get isPhysicalKeyboardEnter =>
deviceType == ui.KeyEventDeviceType.keyboard &&
(logicalKey == LogicalKeyboardKey.enter ||
logicalKey == LogicalKeyboardKey.numpadEnter ||
logicalKey == LogicalKeyboardKey.select);
(logicalKey == LogicalKeyboardKey.enter || logicalKey == LogicalKeyboardKey.numpadEnter);
bool get isTvSelectEvent {
if (isPhysicalKeyboardEvent) return false;
// Dpad-center / gamepad-A are TV-remote-only — always treat as TV select,
// regardless of the deviceType claim from the engine.
if (logicalKey == LogicalKeyboardKey.select || logicalKey == LogicalKeyboardKey.gameButtonA) return true;
if (logicalKey == LogicalKeyboardKey.enter || logicalKey == LogicalKeyboardKey.numpadEnter) {
return deviceType != ui.KeyEventDeviceType.keyboard;
}
return false;
if (isPhysicalKeyboardEvent) return false;
return logicalKey == LogicalKeyboardKey.enter || logicalKey == LogicalKeyboardKey.numpadEnter;
}
}
@@ -108,12 +108,11 @@ class AppleTvRemoteTouchService {
if (position == null) return;
_moveTouch(position.$1, position.$2);
case 'ended':
final position = _positionFrom(arguments);
if (position == null) {
_resetTouch();
return;
}
_moveTouch(position.$1, position.$2);
// Drop the lift frame: the final position on touchesEnded is
// unreliable on the Siri Remote — a natural finger pivot during
// lift can register enough delta from the post-last-swipe anchor
// to fire a stray opposite-direction swipe. In-gesture 'move'
// events have already covered any legitimate swipe motion.
_resetTouch();
case 'cancelled':
_resetTouch();
+8
View File
@@ -9,6 +9,14 @@ import 'package:flutter/widgets.dart';
/// Used by companion remotes, Apple TV touch input, and gamepad services to
/// translate external input into focus-tree key events.
void simulateKeyPress(LogicalKeyboardKey logicalKey) {
// The dispatch below is deferred via addPostFrameCallback to ensure the
// focus tree is settled before we walk it. That post-frame callback only
// fires after a frame actually renders — and when Flutter is idle (no
// animations, no rebuilds), the engine will never schedule one on its
// own, so the callback hangs indefinitely. Force a frame so external
// input (gamepad, tvOS remote, companion remote) always advances focus
// immediately rather than batching until something else wakes the engine.
scheduleFrameIfIdle();
SchedulerBinding.instance.addPostFrameCallback((_) {
final focusNode = FocusManager.instance.primaryFocus;
if (focusNode == null) return;
+1 -1
View File
@@ -1,7 +1,7 @@
name: plezy
description: "A beautiful Plex and Jellyfin client for Flutter"
publish_to: "none"
version: 2.0.0+86
version: 2.0.0+87
environment:
sdk: ">=3.10.7 <4.0.0"
@@ -119,6 +119,21 @@ void main() {
expect(harness.keys, [LogicalKeyboardKey.arrowLeft]);
});
test('ended position past threshold opposite of the last move does not fire a reverse swipe', () async {
final harness = _Harness();
// User swipes left, then releases the finger. The final lift
// position registers past the swipe threshold from the post-swipe
// anchor in the *opposite* direction — natural finger pivot during
// a lift. The previous implementation called _moveTouch on the
// ended event and re-fired a stray arrowRight here.
await harness.send('started', x: 500, y: 500);
await harness.send('move', x: 380, y: 500);
await harness.send('ended', x: 600, y: 500);
expect(harness.keys, [LogicalKeyboardKey.arrowLeft]);
});
test('deduplicates touch tap and click fallback select events', () async {
final harness = _Harness();
+11 -3
View File
@@ -126,8 +126,16 @@ void main() {
expect(find.byType(Dialog), findsOneWidget);
});
testWidgets('tvOS keyboard-mapped select submits without opening virtual keyboard', (tester) async {
testWidgets('tvOS engine-synthesized select opens the virtual keyboard', (tester) async {
// The custom Flutter tvOS engine emits Siri Remote center-dpad presses
// as `LogicalKeyboardKey.select` with `deviceType=keyboard` (via the
// legacy `flutter/keyevent` Android DPAD_CENTER path). On Apple TV this
// must open the on-screen keyboard, not submit the form. Previously
// `isPhysicalKeyboardEnter` matched select+keyboard and routed through
// `_submitTextInput`, which silently triggered form submit on every
// dpad center press (e.g. immediate validation error on empty fields).
TvDetectionService.debugSetAppleTVOverride(true);
await _setTvSurfaceSize(tester);
final controller = TextEditingController(text: 'query');
final fieldFocusNode = FocusNode(debugLabel: 'search_field');
String? submitted;
@@ -151,8 +159,8 @@ void main() {
await tester.sendKeyEvent(LogicalKeyboardKey.select);
await tester.pumpAndSettle();
expect(submitted, 'query');
expect(find.byType(Dialog), findsNothing);
expect(submitted, isNull);
expect(find.byType(Dialog), findsOneWidget);
});
testWidgets('tvOS text field handles physical keyboard text editing without opening virtual keyboard', (
+72 -72
View File
@@ -7,25 +7,25 @@
objects = {
/* Begin PBXBuildFile section */
0A4E3554C5AD1373495F5434 /* messages.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C8E3486BF50440024D81B1E /* messages.g.swift */; };
24753D6DD9098E97989137A6 /* PackageInfoPlusPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83C51CAD792E5C69AA4F971A /* PackageInfoPlusPlugin.swift */; };
31477C4FBA7BF70CAFCDC566 /* DeviceInfoPlusPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98ED539F08FAE8E8B964C7BE /* DeviceInfoPlusPlugin.swift */; };
055E465F9095D0B6E9B91D46 /* PathProviderPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41AA251EF365516E2AC5287 /* PathProviderPlugin.swift */; };
35DB0C8FEF635A3BCA0B722A /* PackageInfoPlusPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9426EFA282CDA8E0E98EEE9 /* PackageInfoPlusPlugin.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
4E9365FA67E94D8A289FE862 /* PathMonitorConnectivityProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA12E2C6063C5799C38CAA95 /* PathMonitorConnectivityProvider.swift */; };
5C71F5F7B33075F2B007825B /* MpvPlayerPluginShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73645904F226A24585A092CE /* MpvPlayerPluginShared.swift */; };
691577F0EB3F4EB1A5160280 /* MpvPlayerCoreBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52A3BDA46E79969EA1DF3AC /* MpvPlayerCoreBase.swift */; };
6F3C0DD6F2F8DA14E7E2F386 /* MpvPlayerCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12B8610AE5D580077264851 /* MpvPlayerCore.swift */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
81325C1CD13794375A81AC02 /* messages.g.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34CD411CCD84E381C4BF4C1B /* messages.g.swift */; };
81F08E404EBEB19B00FF148D /* ConnectivityPlusPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67C3193A50DFDECE2B92D075 /* ConnectivityPlusPlugin.swift */; };
8E5EED3DDAC9455D4DAA9776 /* MpvPlayerPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D7A998830EDC8F77BF521D1 /* MpvPlayerPlugin.swift */; };
937279397427A0E8ECC70A3A /* PathProviderPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 217BA48DC884CB7ADD43CF88 /* PathProviderPlugin.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
A7596F780E93AF0BE3838A26 /* ConnectivityProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CCA7E80F3A99D8759F2E59F /* ConnectivityProvider.swift */; };
AA34E3E5872B3792D6959EAA /* MpvPipController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2635E12EB9322B151EE5127 /* MpvPipController.swift */; };
AFCEB532D567638EF6707333 /* ConnectivityProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C9575190150A93F97270FC0 /* ConnectivityProvider.swift */; };
C6A15611158B29B0FF43A960 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824D2C68D1F1206932E118C2 /* Pods_Runner.framework */; };
C94CC73C8037BAA385B7ED5C /* SharedPreferencesPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FB5275C65B7F4CC7DD45DF /* SharedPreferencesPlugin.swift */; };
F85DEBB1878182EEE1DC542A /* ConnectivityPlusPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 936A41610C7269D52E5E51FF /* ConnectivityPlusPlugin.swift */; };
CD1C0534948840272E58248E /* PathMonitorConnectivityProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AEF79DFBD1D80F00AB39CDA /* PathMonitorConnectivityProvider.swift */; };
E3DEAD2AAFC347A2E55AC0F7 /* SharedPreferencesPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0455EBA0EF4A61D3B71D2D7 /* SharedPreferencesPlugin.swift */; };
E79A4474D308631AFA59CAE7 /* DeviceInfoPlusPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E1F41676FEF1AB57076F8B9 /* DeviceInfoPlusPlugin.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -44,19 +44,18 @@
/* Begin PBXFileReference section */
04DD35536DEE7C27FFA53862 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
0C25F4F2367A30B47E945AD6 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
0C8E3486BF50440024D81B1E /* messages.g.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = messages.g.swift; sourceTree = "<group>"; };
217BA48DC884CB7ADD43CF88 /* PathProviderPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PathProviderPlugin.swift; sourceTree = "<group>"; };
35FB5275C65B7F4CC7DD45DF /* SharedPreferencesPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SharedPreferencesPlugin.swift; sourceTree = "<group>"; };
34CD411CCD84E381C4BF4C1B /* messages.g.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = messages.g.swift; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3C9575190150A93F97270FC0 /* ConnectivityProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConnectivityProvider.swift; sourceTree = "<group>"; };
3CCA7E80F3A99D8759F2E59F /* ConnectivityProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConnectivityProvider.swift; sourceTree = "<group>"; };
420881FB6A648A2AFD39FFF2 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
5E1F41676FEF1AB57076F8B9 /* DeviceInfoPlusPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DeviceInfoPlusPlugin.swift; sourceTree = "<group>"; };
67C3193A50DFDECE2B92D075 /* ConnectivityPlusPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConnectivityPlusPlugin.swift; sourceTree = "<group>"; };
6AEF79DFBD1D80F00AB39CDA /* PathMonitorConnectivityProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PathMonitorConnectivityProvider.swift; sourceTree = "<group>"; };
73645904F226A24585A092CE /* MpvPlayerPluginShared.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MpvPlayerPluginShared.swift; path = ../shared/apple/MpvPlayer/MpvPlayerPluginShared.swift; sourceTree = "<source_root>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
824D2C68D1F1206932E118C2 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83C51CAD792E5C69AA4F971A /* PackageInfoPlusPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PackageInfoPlusPlugin.swift; sourceTree = "<group>"; };
936A41610C7269D52E5E51FF /* ConnectivityPlusPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConnectivityPlusPlugin.swift; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -64,12 +63,13 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
98ED539F08FAE8E8B964C7BE /* DeviceInfoPlusPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DeviceInfoPlusPlugin.swift; sourceTree = "<group>"; };
9D7A998830EDC8F77BF521D1 /* MpvPlayerPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MpvPlayerPlugin.swift; path = ../ios/Runner/MpvPlayer/MpvPlayerPlugin.swift; sourceTree = "<source_root>"; };
A12B8610AE5D580077264851 /* MpvPlayerCore.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MpvPlayerCore.swift; path = ../ios/Runner/MpvPlayer/MpvPlayerCore.swift; sourceTree = "<source_root>"; };
A2635E12EB9322B151EE5127 /* MpvPipController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MpvPipController.swift; path = ../ios/Runner/MpvPlayer/MpvPipController.swift; sourceTree = "<source_root>"; };
AA12E2C6063C5799C38CAA95 /* PathMonitorConnectivityProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PathMonitorConnectivityProvider.swift; sourceTree = "<group>"; };
C0455EBA0EF4A61D3B71D2D7 /* SharedPreferencesPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SharedPreferencesPlugin.swift; sourceTree = "<group>"; };
D41AA251EF365516E2AC5287 /* PathProviderPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PathProviderPlugin.swift; sourceTree = "<group>"; };
D52A3BDA46E79969EA1DF3AC /* MpvPlayerCoreBase.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MpvPlayerCoreBase.swift; path = ../shared/apple/MpvPlayer/MpvPlayerCoreBase.swift; sourceTree = "<source_root>"; };
F9426EFA282CDA8E0E98EEE9 /* PackageInfoPlusPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PackageInfoPlusPlugin.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -84,26 +84,36 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0BB116AB9B63B9251A577795 /* connectivity_plus */ = {
02A6A190E05475F583874D9C /* package_info_plus */ = {
isa = PBXGroup;
children = (
936A41610C7269D52E5E51FF /* ConnectivityPlusPlugin.swift */,
3C9575190150A93F97270FC0 /* ConnectivityProvider.swift */,
AA12E2C6063C5799C38CAA95 /* PathMonitorConnectivityProvider.swift */,
);
name = connectivity_plus;
path = connectivity_plus;
sourceTree = "<group>";
};
5167AAFF7134262A07EBBC7C /* package_info_plus */ = {
isa = PBXGroup;
children = (
83C51CAD792E5C69AA4F971A /* PackageInfoPlusPlugin.swift */,
F9426EFA282CDA8E0E98EEE9 /* PackageInfoPlusPlugin.swift */,
);
name = package_info_plus;
path = package_info_plus;
sourceTree = "<group>";
};
24CE237B5ECBF841DDDAD2D1 /* shared_preferences_foundation */ = {
isa = PBXGroup;
children = (
C0455EBA0EF4A61D3B71D2D7 /* SharedPreferencesPlugin.swift */,
34CD411CCD84E381C4BF4C1B /* messages.g.swift */,
);
name = shared_preferences_foundation;
path = shared_preferences_foundation;
sourceTree = "<group>";
};
25FB49FF35E9FB1E7A2040EF /* connectivity_plus */ = {
isa = PBXGroup;
children = (
67C3193A50DFDECE2B92D075 /* ConnectivityPlusPlugin.swift */,
3CCA7E80F3A99D8759F2E59F /* ConnectivityProvider.swift */,
6AEF79DFBD1D80F00AB39CDA /* PathMonitorConnectivityProvider.swift */,
);
name = connectivity_plus;
path = connectivity_plus;
sourceTree = "<group>";
};
53CDD29681161166962B9FA5 /* Pods */ = {
isa = PBXGroup;
children = (
@@ -122,23 +132,10 @@
name = Frameworks;
sourceTree = "<group>";
};
6C18DC1E07D29FCDF63F3159 /* Plugins */ = {
6B0884FDB3DBCBC1E7F0CBAD /* device_info_plus */ = {
isa = PBXGroup;
children = (
ACB880260B35BB030208DF38 /* shared_preferences_foundation */,
5167AAFF7134262A07EBBC7C /* package_info_plus */,
9DF350B3C8D3FFF46CF8FEF7 /* path_provider */,
7CEBB3A4438717E61CFCBA1E /* device_info_plus */,
0BB116AB9B63B9251A577795 /* connectivity_plus */,
);
name = Plugins;
path = Plugins;
sourceTree = "<group>";
};
7CEBB3A4438717E61CFCBA1E /* device_info_plus */ = {
isa = PBXGroup;
children = (
98ED539F08FAE8E8B964C7BE /* DeviceInfoPlusPlugin.swift */,
5E1F41676FEF1AB57076F8B9 /* DeviceInfoPlusPlugin.swift */,
);
name = device_info_plus;
path = device_info_plus;
@@ -184,30 +181,11 @@
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
BF0B7DFE378943E9D7865D18 /* MpvPlayer */,
6C18DC1E07D29FCDF63F3159 /* Plugins */,
D58B788B11920D95BC7D750C /* Plugins */,
);
path = Runner;
sourceTree = "<group>";
};
9DF350B3C8D3FFF46CF8FEF7 /* path_provider */ = {
isa = PBXGroup;
children = (
217BA48DC884CB7ADD43CF88 /* PathProviderPlugin.swift */,
);
name = path_provider;
path = path_provider;
sourceTree = "<group>";
};
ACB880260B35BB030208DF38 /* shared_preferences_foundation */ = {
isa = PBXGroup;
children = (
35FB5275C65B7F4CC7DD45DF /* SharedPreferencesPlugin.swift */,
0C8E3486BF50440024D81B1E /* messages.g.swift */,
);
name = shared_preferences_foundation;
path = shared_preferences_foundation;
sourceTree = "<group>";
};
BF0B7DFE378943E9D7865D18 /* MpvPlayer */ = {
isa = PBXGroup;
children = (
@@ -221,6 +199,28 @@
path = Runner/MpvPlayer;
sourceTree = "<group>";
};
D58B788B11920D95BC7D750C /* Plugins */ = {
isa = PBXGroup;
children = (
24CE237B5ECBF841DDDAD2D1 /* shared_preferences_foundation */,
02A6A190E05475F583874D9C /* package_info_plus */,
DF39F6BC85D449736C737F18 /* path_provider */,
6B0884FDB3DBCBC1E7F0CBAD /* device_info_plus */,
25FB49FF35E9FB1E7A2040EF /* connectivity_plus */,
);
name = Plugins;
path = Plugins;
sourceTree = "<group>";
};
DF39F6BC85D449736C737F18 /* path_provider */ = {
isa = PBXGroup;
children = (
D41AA251EF365516E2AC5287 /* PathProviderPlugin.swift */,
);
name = path_provider;
path = path_provider;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -380,14 +380,14 @@
6F3C0DD6F2F8DA14E7E2F386 /* MpvPlayerCore.swift in Sources */,
8E5EED3DDAC9455D4DAA9776 /* MpvPlayerPlugin.swift in Sources */,
AA34E3E5872B3792D6959EAA /* MpvPipController.swift in Sources */,
C94CC73C8037BAA385B7ED5C /* SharedPreferencesPlugin.swift in Sources */,
0A4E3554C5AD1373495F5434 /* messages.g.swift in Sources */,
24753D6DD9098E97989137A6 /* PackageInfoPlusPlugin.swift in Sources */,
937279397427A0E8ECC70A3A /* PathProviderPlugin.swift in Sources */,
31477C4FBA7BF70CAFCDC566 /* DeviceInfoPlusPlugin.swift in Sources */,
F85DEBB1878182EEE1DC542A /* ConnectivityPlusPlugin.swift in Sources */,
AFCEB532D567638EF6707333 /* ConnectivityProvider.swift in Sources */,
4E9365FA67E94D8A289FE862 /* PathMonitorConnectivityProvider.swift in Sources */,
E3DEAD2AAFC347A2E55AC0F7 /* SharedPreferencesPlugin.swift in Sources */,
81325C1CD13794375A81AC02 /* messages.g.swift in Sources */,
35DB0C8FEF635A3BCA0B722A /* PackageInfoPlusPlugin.swift in Sources */,
055E465F9095D0B6E9B91D46 /* PathProviderPlugin.swift in Sources */,
E79A4474D308631AFA59CAE7 /* DeviceInfoPlusPlugin.swift in Sources */,
81F08E404EBEB19B00FF148D /* ConnectivityPlusPlugin.swift in Sources */,
A7596F780E93AF0BE3838A26 /* ConnectivityProvider.swift in Sources */,
CD1C0534948840272E58248E /* PathMonitorConnectivityProvider.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+1 -1
View File
@@ -1 +1 @@
3.41.6+5
3.41.6+6
+18
View File
@@ -78,5 +78,23 @@ plugins.each do |plugin_name, files|
end
end
# Remove stale Runner/-level Swift refs from earlier engine workarounds.
# Currently nothing needs to live directly under tvos/Runner/ besides
# AppDelegate.swift (which the Xcode project tracks on its own); the
# SiriRemoteDpadBridge.swift workaround was removed once the engine patch
# took over dpad click handling.
STALE_RUNNER_LOCAL_SOURCES = %w[SiriRemoteDpadBridge.swift]
project.files.select { |f| STALE_RUNNER_LOCAL_SOURCES.include?(f.display_name) }.each do |f|
f.remove_from_project
puts "[rm ] stale ref: #{f.display_name}"
end
project.targets.each do |t|
t.build_phases.each do |phase|
next unless phase.respond_to?(:files)
phase.files.delete_if { |bf| bf.file_ref.nil? }
end
end
project.save
puts "Saved"