mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-01 00:28:18 +08:00
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:PiliPlus/utils/utils.dart';
|
||||||
|
|
||||||
enum UaType {
|
enum UaType {
|
||||||
mob(
|
mob(
|
||||||
'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36',
|
'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36',
|
||||||
@@ -6,6 +8,8 @@ enum UaType {
|
|||||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15',
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static UaType get platformUA => Utils.isMobile ? mob : pc;
|
||||||
|
|
||||||
final String ua;
|
final String ua;
|
||||||
const UaType(this.ua);
|
const UaType(this.ua);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:PiliPlus/pages/common/slide/common_slide_page.dart';
|
|||||||
import 'package:PiliPlus/pages/video/controller.dart';
|
import 'package:PiliPlus/pages/video/controller.dart';
|
||||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/selectable_text.dart';
|
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/selectable_text.dart';
|
||||||
import 'package:PiliPlus/utils/duration_utils.dart';
|
import 'package:PiliPlus/utils/duration_utils.dart';
|
||||||
|
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -53,16 +54,19 @@ class _AiDetailState extends State<AiConclusionPanel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
late Key _key;
|
late Key _key;
|
||||||
|
late bool _isNested;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_key = ValueKey(PrimaryScrollController.of(context).hashCode);
|
final controller = PrimaryScrollController.of(context);
|
||||||
|
_isNested = controller is ExtendedNestedScrollController;
|
||||||
|
_key = ValueKey(controller.hashCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(ThemeData theme) {
|
Widget buildList(ThemeData theme) {
|
||||||
return CustomScrollView(
|
final child = CustomScrollView(
|
||||||
key: _key,
|
key: _key,
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
slivers: [
|
slivers: [
|
||||||
@@ -158,5 +162,12 @@ class _AiDetailState extends State<AiConclusionPanel>
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
if (_isNested) {
|
||||||
|
return ExtendedVisibilityDetector(
|
||||||
|
uniqueKey: const Key('ai-conclusion'),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:PiliPlus/pages/video/note/controller.dart';
|
|||||||
import 'package:PiliPlus/pages/webview/view.dart';
|
import 'package:PiliPlus/pages/webview/view.dart';
|
||||||
import 'package:PiliPlus/utils/accounts.dart';
|
import 'package:PiliPlus/utils/accounts.dart';
|
||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
|
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
@@ -89,81 +90,89 @@ class _NoteListPageState extends State<NoteListPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
late Key _key;
|
late Key _key;
|
||||||
|
late bool _isNested;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_key = ValueKey(PrimaryScrollController.of(context).hashCode);
|
final controller = PrimaryScrollController.of(context);
|
||||||
|
_isNested = controller is ExtendedNestedScrollController;
|
||||||
|
_key = ValueKey(controller.hashCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(ThemeData theme) {
|
Widget buildList(ThemeData theme) {
|
||||||
return refreshIndicator(
|
Widget child = refreshIndicator(
|
||||||
onRefresh: _controller.onRefresh,
|
onRefresh: _controller.onRefresh,
|
||||||
child: Column(
|
child: CustomScrollView(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
key: _key,
|
||||||
children: [
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
Expanded(
|
slivers: [
|
||||||
child: CustomScrollView(
|
SliverPadding(
|
||||||
key: _key,
|
padding: const EdgeInsets.only(bottom: 100),
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
sliver: Obx(
|
||||||
slivers: [
|
() => _buildBody(theme, _controller.loadingState.value),
|
||||||
SliverPadding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 100),
|
|
||||||
sliver: Obx(
|
|
||||||
() => _buildBody(theme, _controller.loadingState.value),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
left: 12,
|
|
||||||
right: 12,
|
|
||||||
top: 6,
|
|
||||||
bottom: MediaQuery.viewPaddingOf(context).bottom + 6,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: theme.colorScheme.onInverseSurface,
|
|
||||||
border: Border(
|
|
||||||
top: BorderSide(
|
|
||||||
width: 0.5,
|
|
||||||
color: theme.colorScheme.outline.withValues(alpha: 0.1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Builder(
|
|
||||||
builder: (context) => FilledButton.tonal(
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(6)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
if (!Accounts.main.isLogin) {
|
|
||||||
SmartDialog.showToast('账号未登录');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Scaffold.of(context).showBottomSheet(
|
|
||||||
constraints: const BoxConstraints(),
|
|
||||||
(context) => WebviewPage(
|
|
||||||
oid: widget.oid,
|
|
||||||
title: widget.title,
|
|
||||||
url:
|
|
||||||
'https://www.bilibili.com/h5/note-app?oid=${widget.oid}&pagefrom=ugcvideo&is_stein_gate=${widget.isStein ? 1 : 0}',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: const Text('开始记笔记'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
if (_isNested) {
|
||||||
|
child = ExtendedVisibilityDetector(
|
||||||
|
uniqueKey: const Key('note-list'),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Expanded(child: child),
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 12,
|
||||||
|
right: 12,
|
||||||
|
top: 6,
|
||||||
|
bottom: MediaQuery.viewPaddingOf(context).bottom + 6,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: theme.colorScheme.onInverseSurface,
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(
|
||||||
|
width: 0.5,
|
||||||
|
color: theme.colorScheme.outline.withValues(alpha: 0.1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) => FilledButton.tonal(
|
||||||
|
style: FilledButton.styleFrom(
|
||||||
|
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(6)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
if (!Accounts.main.isLogin) {
|
||||||
|
SmartDialog.showToast('账号未登录');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Scaffold.of(context).showBottomSheet(
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
|
(context) => WebviewPage(
|
||||||
|
oid: widget.oid,
|
||||||
|
title: widget.title,
|
||||||
|
url:
|
||||||
|
'https://www.bilibili.com/h5/note-app?oid=${widget.oid}&pagefrom=ugcvideo&is_stein_gate=${widget.isStein ? 1 : 0}',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('开始记笔记'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBody(
|
Widget _buildBody(
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import 'package:PiliPlus/utils/duration_utils.dart';
|
|||||||
import 'package:PiliPlus/utils/extension.dart';
|
import 'package:PiliPlus/utils/extension.dart';
|
||||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||||
import 'package:flutter/foundation.dart' show kDebugMode;
|
import 'package:flutter/foundation.dart' show kDebugMode;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart' show FilteringTextInputFormatter;
|
import 'package:flutter/services.dart' show FilteringTextInputFormatter;
|
||||||
@@ -239,11 +240,14 @@ class _PostPanelState extends State<PostPanel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
late Key _key;
|
late Key _key;
|
||||||
|
late bool _isNested;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_key = ValueKey(PrimaryScrollController.of(context).hashCode);
|
final controller = PrimaryScrollController.of(context);
|
||||||
|
_isNested = controller is ExtendedNestedScrollController;
|
||||||
|
_key = ValueKey(controller.hashCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -252,18 +256,25 @@ class _PostPanelState extends State<PostPanel>
|
|||||||
return errorWidget();
|
return errorWidget();
|
||||||
}
|
}
|
||||||
final bottom = MediaQuery.viewPaddingOf(context).bottom;
|
final bottom = MediaQuery.viewPaddingOf(context).bottom;
|
||||||
|
Widget child = ListView.builder(
|
||||||
|
key: _key,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
padding: EdgeInsets.only(bottom: 88 + bottom),
|
||||||
|
itemCount: list.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return _buildItem(theme, index, list[index]);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (_isNested) {
|
||||||
|
child = ExtendedVisibilityDetector(
|
||||||
|
uniqueKey: const Key('post-panel'),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
return Stack(
|
return Stack(
|
||||||
clipBehavior: Clip.none,
|
clipBehavior: Clip.none,
|
||||||
children: [
|
children: [
|
||||||
ListView.builder(
|
child,
|
||||||
key: _key,
|
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
|
||||||
padding: EdgeInsets.only(bottom: 88 + bottom),
|
|
||||||
itemCount: list.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return _buildItem(theme, index, list[index]);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 16,
|
right: 16,
|
||||||
bottom: 16 + bottom,
|
bottom: 16 + bottom,
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(ThemeData theme) {
|
Widget buildList(ThemeData theme) {
|
||||||
return refreshIndicator(
|
final child = refreshIndicator(
|
||||||
onRefresh: _controller.onRefresh,
|
onRefresh: _controller.onRefresh,
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
key: ValueKey(scrollController.hashCode),
|
key: ValueKey(scrollController.hashCode),
|
||||||
@@ -161,6 +161,13 @@ class _VideoReplyReplyPanelState extends State<VideoReplyReplyPanel>
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
if (widget.isNested) {
|
||||||
|
return ExtendedVisibilityDetector(
|
||||||
|
uniqueKey: Key(_tag),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _header(ThemeData theme, ReplyInfo firstFloor) {
|
Widget _header(ThemeData theme, ReplyInfo firstFloor) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:PiliPlus/pages/common/slide/common_slide_page.dart';
|
|||||||
import 'package:PiliPlus/pages/video/controller.dart';
|
import 'package:PiliPlus/pages/video/controller.dart';
|
||||||
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
import 'package:PiliPlus/plugin/pl_player/controller.dart';
|
||||||
import 'package:PiliPlus/utils/duration_utils.dart';
|
import 'package:PiliPlus/utils/duration_utils.dart';
|
||||||
|
import 'package:extended_nested_scroll_view/extended_nested_scroll_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
@@ -78,16 +79,19 @@ class _ViewPointsPageState extends State<ViewPointsPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
late Key _key;
|
late Key _key;
|
||||||
|
late bool _isNested;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
_key = ValueKey(PrimaryScrollController.of(context).hashCode);
|
final controller = PrimaryScrollController.of(context);
|
||||||
|
_isNested = controller is ExtendedNestedScrollController;
|
||||||
|
_key = ValueKey(controller.hashCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildList(ThemeData theme) {
|
Widget buildList(ThemeData theme) {
|
||||||
return ListView.builder(
|
final child = ListView.builder(
|
||||||
key: _key,
|
key: _key,
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
@@ -109,6 +113,13 @@ class _ViewPointsPageState extends State<ViewPointsPage>
|
|||||||
return _buildItem(theme, segment, isCurr);
|
return _buildItem(theme, segment, isCurr);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
if (_isNested) {
|
||||||
|
return ExtendedVisibilityDetector(
|
||||||
|
uniqueKey: const Key('viewpoints'),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildItem(ThemeData theme, Segment segment, bool isCurr) {
|
Widget _buildItem(ThemeData theme, Segment segment, bool isCurr) {
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ class WebviewPage extends StatefulWidget {
|
|||||||
|
|
||||||
class _WebviewPageState extends State<WebviewPage> {
|
class _WebviewPageState extends State<WebviewPage> {
|
||||||
late final String _url = widget.url ?? Get.parameters['url'] ?? '';
|
late final String _url = widget.url ?? Get.parameters['url'] ?? '';
|
||||||
late final UaType uaType =
|
late final UaType uaType;
|
||||||
widget.uaType ?? UaType.values.byName(Get.parameters['uaType'] ?? 'mob');
|
|
||||||
final RxString title = ''.obs;
|
final RxString title = ''.obs;
|
||||||
final RxDouble progress = 1.0.obs;
|
final RxDouble progress = 1.0.obs;
|
||||||
bool _inApp = false;
|
bool _inApp = false;
|
||||||
@@ -47,6 +46,10 @@ class _WebviewPageState extends State<WebviewPage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
late final uaType = Get.parameters['uaType'];
|
||||||
|
this.uaType =
|
||||||
|
widget.uaType ??
|
||||||
|
(uaType != null ? UaType.values.byName(uaType) : UaType.platformUA);
|
||||||
if (Get.arguments case Map map) {
|
if (Get.arguments case Map map) {
|
||||||
_inApp = map['inApp'] ?? false;
|
_inApp = map['inApp'] ?? false;
|
||||||
_off = map['off'] ?? false;
|
_off = map['off'] ?? false;
|
||||||
|
|||||||
@@ -505,7 +505,7 @@ packages:
|
|||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: mod
|
ref: mod
|
||||||
resolved-ref: "07dbeaa6f4352cd605e2292f073eca3538635ef3"
|
resolved-ref: "4bb4e827628b3b7ccc88a4b98ef76a036a5a51ac"
|
||||||
url: "https://github.com/bggRGjQaUbCoE/extended_nested_scroll_view.git"
|
url: "https://github.com/bggRGjQaUbCoE/extended_nested_scroll_view.git"
|
||||||
source: git
|
source: git
|
||||||
version: "6.2.1"
|
version: "6.2.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user