mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
desktop pip
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -29,7 +29,6 @@ import 'package:PiliPlus/utils/storage_key.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:canvas_danmaku/canvas_danmaku.dart';
|
||||
import 'package:floating/floating.dart';
|
||||
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart' show SystemUiOverlayStyle;
|
||||
@@ -181,23 +180,26 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (Platform.isAndroid && Floating().isPipMode) {
|
||||
return videoPlayerPanel(
|
||||
Widget child;
|
||||
if (plPlayerController.isPipMode) {
|
||||
child = videoPlayerPanel(
|
||||
isFullScreen,
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
isPipMode: true,
|
||||
needDm: !plPlayerController.pipNoDanmaku,
|
||||
);
|
||||
} else {
|
||||
child = childWhenDisabled;
|
||||
}
|
||||
if (plPlayerController.keyboardControl) {
|
||||
return PlayerFocus(
|
||||
child = PlayerFocus(
|
||||
plPlayerController: plPlayerController,
|
||||
onSendDanmaku: _liveRoomController.onSendDanmaku,
|
||||
child: childWhenDisabled,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
return childWhenDisabled;
|
||||
return child;
|
||||
}
|
||||
|
||||
Widget videoPlayerPanel(
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/widgets/common_btn.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:floating/floating.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
@@ -109,10 +110,14 @@ class LiveHeaderControl extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
if (Platform.isAndroid)
|
||||
if (Platform.isAndroid || Utils.isDesktop)
|
||||
ComBtn(
|
||||
tooltip: '画中画',
|
||||
onTap: () async {
|
||||
if (Utils.isDesktop) {
|
||||
plPlayerController.toggleDesktopPip();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
var floating = Floating();
|
||||
if ((await floating.isPipAvailable) == true) {
|
||||
|
||||
@@ -429,7 +429,8 @@ class VideoDetailController extends GetxController
|
||||
|
||||
bool get horizontalScreen => plPlayerController.horizontalScreen;
|
||||
|
||||
bool get showVideoSheet => !horizontalScreen && !isPortrait;
|
||||
bool get showVideoSheet =>
|
||||
(!horizontalScreen && !isPortrait) || plPlayerController.isDesktopPip;
|
||||
|
||||
int? _lastPos;
|
||||
late final List<PostSegmentModel> postList = [];
|
||||
|
||||
@@ -1456,15 +1456,6 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
),
|
||||
);
|
||||
|
||||
Widget autoChoose(Widget childWhenDisabled) {
|
||||
if (Platform.isAndroid) {
|
||||
return Floating().isPipMode
|
||||
? plPlayer(width: maxWidth, height: maxHeight, isPipMode: true)
|
||||
: childWhenDisabled;
|
||||
}
|
||||
return childWhenDisabled;
|
||||
}
|
||||
|
||||
late ThemeData themeData;
|
||||
late bool isPortrait;
|
||||
late double maxWidth;
|
||||
@@ -1473,14 +1464,16 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget child;
|
||||
if (!videoDetailController.horizontalScreen) {
|
||||
child = autoChoose(childWhenDisabled);
|
||||
if (videoDetailController.plPlayerController.isPipMode) {
|
||||
child = plPlayer(width: maxWidth, height: maxHeight, isPipMode: true);
|
||||
} else if (!videoDetailController.horizontalScreen) {
|
||||
child = childWhenDisabled;
|
||||
} else if (maxWidth > maxHeight * 1.25) {
|
||||
child = autoChoose(childWhenDisabledLandscape);
|
||||
child = childWhenDisabledLandscape;
|
||||
} else if (maxWidth * (9 / 16) < (2 / 5) * maxHeight) {
|
||||
child = autoChoose(childWhenDisabled);
|
||||
child = childWhenDisabled;
|
||||
} else {
|
||||
child = autoChoose(childWhenDisabledAlmostSquare);
|
||||
child = childWhenDisabledAlmostSquare;
|
||||
}
|
||||
if (videoDetailController.plPlayerController.keyboardControl) {
|
||||
child = PlayerFocus(
|
||||
|
||||
@@ -1925,7 +1925,9 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
||||
color: Colors.white,
|
||||
),
|
||||
onPressed: () {
|
||||
if (isFullScreen) {
|
||||
if (plPlayerController.isDesktopPip) {
|
||||
plPlayerController.exitDesktopPip();
|
||||
} else if (isFullScreen) {
|
||||
plPlayerController.triggerFullScreen(status: false);
|
||||
} else if (!horizontalScreen && !isPortrait) {
|
||||
verticalScreenForTwoSeconds();
|
||||
@@ -2123,7 +2125,7 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
||||
},
|
||||
),
|
||||
),
|
||||
if (Platform.isAndroid)
|
||||
if (Platform.isAndroid || Utils.isDesktop)
|
||||
SizedBox(
|
||||
width: 42,
|
||||
height: 34,
|
||||
@@ -2133,6 +2135,10 @@ class HeaderControlState extends TripleState<HeaderControl> {
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
),
|
||||
onPressed: () async {
|
||||
if (Utils.isDesktop) {
|
||||
plPlayerController.toggleDesktopPip();
|
||||
return;
|
||||
}
|
||||
bool canUsePiP = await Floating().isPipAvailable;
|
||||
plPlayerController.hiddenControls(false);
|
||||
if (canUsePiP) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart';
|
||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/storage_key.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart'
|
||||
show KeyDownEvent, KeyUpEvent, LogicalKeyboardKey;
|
||||
@@ -71,7 +72,9 @@ class PlayerFocus extends StatelessWidget {
|
||||
return true;
|
||||
|
||||
case LogicalKeyboardKey.escape:
|
||||
if (isFullScreen) {
|
||||
if (plPlayerController.isDesktopPip) {
|
||||
plPlayerController.exitDesktopPip();
|
||||
} else if (isFullScreen) {
|
||||
plPlayerController.triggerFullScreen(status: false);
|
||||
} else {
|
||||
Get.back();
|
||||
@@ -94,6 +97,10 @@ class PlayerFocus extends StatelessWidget {
|
||||
}
|
||||
return true;
|
||||
|
||||
case LogicalKeyboardKey.keyP when (Utils.isDesktop && hasPlayer):
|
||||
plPlayerController.toggleDesktopPip();
|
||||
return true;
|
||||
|
||||
case LogicalKeyboardKey.arrowUp:
|
||||
if (hasPlayer) {
|
||||
final volume = math.min(1.0, plPlayerController.volume.value + 0.1);
|
||||
|
||||
@@ -41,6 +41,7 @@ import 'package:canvas_danmaku/canvas_danmaku.dart';
|
||||
import 'package:crclib/catalog.dart';
|
||||
import 'package:dio/dio.dart' show Options;
|
||||
import 'package:easy_debounce/easy_throttle.dart';
|
||||
import 'package:floating/floating.dart';
|
||||
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -53,6 +54,7 @@ import 'package:media_kit_video/media_kit_video.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:universal_platform/universal_platform.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
class PlPlayerController {
|
||||
Player? _videoPlayerController;
|
||||
@@ -253,6 +255,51 @@ class PlPlayerController {
|
||||
late final RxBool enableShowLiveDanmaku = Pref.enableShowLiveDanmaku.obs;
|
||||
|
||||
late final bool autoPiP = Pref.autoPiP;
|
||||
bool get isPipMode =>
|
||||
(Platform.isAndroid && Floating().isPipMode) ||
|
||||
(Utils.isDesktop && isDesktopPip);
|
||||
late bool isDesktopPip = false;
|
||||
late Rect _lastWindowBounds;
|
||||
|
||||
void exitDesktopPip() {
|
||||
isDesktopPip = false;
|
||||
|
||||
windowManager
|
||||
..setTitleBarStyle(TitleBarStyle.normal)
|
||||
..setMinimumSize(const Size(400, 700))
|
||||
..setBounds(_lastWindowBounds)
|
||||
..setAlwaysOnTop(false);
|
||||
}
|
||||
|
||||
Future<void> enterDesktopPip() async {
|
||||
isDesktopPip = true;
|
||||
|
||||
_lastWindowBounds = await windowManager.getBounds();
|
||||
|
||||
windowManager.setTitleBarStyle(TitleBarStyle.hidden);
|
||||
|
||||
late final Size size;
|
||||
final width = this.width ?? 16;
|
||||
final height = this.height ?? 9;
|
||||
if (height > width) {
|
||||
size = Size(400.0, 400.0 * height / width);
|
||||
} else {
|
||||
size = Size(280.0 * width / height, 280.0);
|
||||
}
|
||||
|
||||
await windowManager.setMinimumSize(size);
|
||||
windowManager
|
||||
..setSize(size)
|
||||
..setAlwaysOnTop(true);
|
||||
}
|
||||
|
||||
void toggleDesktopPip() {
|
||||
if (isDesktopPip) {
|
||||
exitDesktopPip();
|
||||
} else {
|
||||
enterDesktopPip();
|
||||
}
|
||||
}
|
||||
|
||||
void enterPip() {
|
||||
if (Get.currentRoute.startsWith('/video')) {
|
||||
|
||||
@@ -59,6 +59,7 @@ import 'package:get/get.dart' hide ContextExtensionss;
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
import 'package:media_kit_video/media_kit_video.dart';
|
||||
import 'package:screen_brightness_platform_interface/screen_brightness_platform_interface.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
class PLVideoPlayer extends StatefulWidget {
|
||||
const PLVideoPlayer({
|
||||
@@ -749,16 +750,17 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
],
|
||||
];
|
||||
|
||||
final flag = isFullScreen || plPlayerController.isDesktopPip;
|
||||
List<BottomControlType> userSpecifyItemRight = [
|
||||
if (plPlayerController.showDmChart) BottomControlType.dmChart,
|
||||
if (plPlayerController.isAnim) BottomControlType.superResolution,
|
||||
if (plPlayerController.showViewPoints) BottomControlType.viewPoints,
|
||||
if (anySeason) BottomControlType.episode,
|
||||
if (isFullScreen) BottomControlType.fit,
|
||||
if (flag) BottomControlType.fit,
|
||||
BottomControlType.aiTranslate,
|
||||
BottomControlType.subtitle,
|
||||
BottomControlType.speed,
|
||||
if (isFullScreen) BottomControlType.qa,
|
||||
if (flag) BottomControlType.qa,
|
||||
BottomControlType.fullscreen,
|
||||
];
|
||||
|
||||
@@ -1308,7 +1310,13 @@ class _PLVideoPlayerState extends State<PLVideoPlayer>
|
||||
isTop: true,
|
||||
controller: animationController,
|
||||
isFullScreen: isFullScreen,
|
||||
child: widget.headerControl,
|
||||
child: plPlayerController.isDesktopPip
|
||||
? GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onPanStart: (_) => windowManager.startDragging(),
|
||||
child: widget.headerControl,
|
||||
)
|
||||
: widget.headerControl,
|
||||
),
|
||||
AppBarAni(
|
||||
isTop: false,
|
||||
|
||||
Reference in New Issue
Block a user