commit
8ec6df2be5
3 files changed
+54
-8
No files matched your search
@@ -386,15 +386,29 @@ final class PipShadowCoordinator: NSObject, AVPictureInPictureControllerDelegate
|
|||||||
guard call.method == "shareText",
|
guard call.method == "shareText",
|
||||||
let arguments = call.arguments as? [String: Any],
|
let arguments = call.arguments as? [String: Any],
|
||||||
let text = arguments["text"] as? String,
|
let text = arguments["text"] as? String,
|
||||||
!text.isEmpty,
|
!text.isEmpty else {
|
||||||
let controller = self?.window?.rootViewController else {
|
|
||||||
result(FlutterError(code: "share_unavailable", message: "Share sheet is unavailable", details: nil))
|
result(FlutterError(code: "share_unavailable", message: "Share sheet is unavailable", details: nil))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let activity = UIActivityViewController(activityItems: [text], applicationActivities: nil)
|
DispatchQueue.main.async {
|
||||||
activity.popoverPresentationController?.sourceView = controller.view
|
guard let controller = self?.sharePresenter() else {
|
||||||
activity.completionWithItemsHandler = { _, _, _, _ in result(nil) }
|
result(FlutterError(code: "share_unavailable", message: "Share sheet is unavailable", details: nil))
|
||||||
controller.present(activity, animated: true)
|
return
|
||||||
|
}
|
||||||
|
let activity = UIActivityViewController(activityItems: [text], applicationActivities: nil)
|
||||||
|
if let popover = activity.popoverPresentationController {
|
||||||
|
popover.sourceView = controller.view
|
||||||
|
popover.sourceRect = CGRect(
|
||||||
|
x: controller.view.bounds.midX,
|
||||||
|
y: controller.view.bounds.midY,
|
||||||
|
width: 0,
|
||||||
|
height: 0
|
||||||
|
)
|
||||||
|
popover.permittedArrowDirections = []
|
||||||
|
}
|
||||||
|
activity.completionWithItemsHandler = { _, _, _, _ in result(nil) }
|
||||||
|
controller.present(activity, animated: true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let thumbnailChannel = FlutterMethodChannel(
|
let thumbnailChannel = FlutterMethodChannel(
|
||||||
@@ -459,6 +473,34 @@ final class PipShadowCoordinator: NSObject, AVPictureInPictureControllerDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 当前前台 Scene 的根控制器之上,最适合展示系统分享面板的控制器。
|
||||||
|
private func sharePresenter() -> UIViewController? {
|
||||||
|
let keyWindow = UIApplication.shared.connectedScenes
|
||||||
|
.compactMap { $0 as? UIWindowScene }
|
||||||
|
.first { $0.activationState == .foregroundActive }?
|
||||||
|
.windows.first { $0.isKeyWindow }
|
||||||
|
guard let rootController = keyWindow?.rootViewController else { return nil }
|
||||||
|
let presenter = topPresentedController(from: rootController)
|
||||||
|
guard presenter.viewIfLoaded?.window != nil else { return nil }
|
||||||
|
return presenter
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 解析已展示页面、导航栈和标签页中的当前可见控制器。
|
||||||
|
private func topPresentedController(from controller: UIViewController) -> UIViewController {
|
||||||
|
if let presented = controller.presentedViewController {
|
||||||
|
return topPresentedController(from: presented)
|
||||||
|
}
|
||||||
|
if let navigation = controller as? UINavigationController,
|
||||||
|
let visible = navigation.visibleViewController {
|
||||||
|
return topPresentedController(from: visible)
|
||||||
|
}
|
||||||
|
if let tabs = controller as? UITabBarController,
|
||||||
|
let selected = tabs.selectedViewController {
|
||||||
|
return topPresentedController(from: selected)
|
||||||
|
}
|
||||||
|
return controller
|
||||||
|
}
|
||||||
|
|
||||||
/// iOS 画中画:影子播放器通道,与 Android 共用同一 channel 名。
|
/// iOS 画中画:影子播放器通道,与 Android 共用同一 channel 名。
|
||||||
private func registerPipChannel(_ engineBridge: FlutterImplicitEngineBridge) {
|
private func registerPipChannel(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||||
let channel = FlutterMethodChannel(
|
let channel = FlutterMethodChannel(
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const double _progressHeight = 2;
|
|||||||
const double _progressHitHeight = 16;
|
const double _progressHitHeight = 16;
|
||||||
const double _pageHorizontal = 20;
|
const double _pageHorizontal = 20;
|
||||||
const double _railRight = 14;
|
const double _railRight = 14;
|
||||||
|
const double _railShiftRight = 8;
|
||||||
const double _railGap = 12;
|
const double _railGap = 12;
|
||||||
const double _railWidth = 56;
|
const double _railWidth = 56;
|
||||||
const double _infoWatchAllGap = 2;
|
const double _infoWatchAllGap = 2;
|
||||||
@@ -234,7 +235,10 @@ class _HomeFeedOverlayState extends State<HomeFeedOverlay> {
|
|||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
bottom: _railBottomOffset,
|
bottom: _railBottomOffset,
|
||||||
),
|
),
|
||||||
child: _rail(),
|
child: Transform.translate(
|
||||||
|
offset: const Offset(_railShiftRight, 0),
|
||||||
|
child: _rail(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ void main() {
|
|||||||
expect(
|
expect(
|
||||||
tester.getRect(find.byKey(const Key('home-feed-action-rail'))).right,
|
tester.getRect(find.byKey(const Key('home-feed-action-rail'))).right,
|
||||||
closeTo(
|
closeTo(
|
||||||
tester.getRect(find.byKey(const Key('home-feed-gesture'))).right - 14,
|
tester.getRect(find.byKey(const Key('home-feed-gesture'))).right - 6,
|
||||||
0.1,
|
0.1,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in new issue
Block a user