Skip to content

Commit 7a77b14

Browse files
committed
现在移动端Nipaplay主题有了 锁定按钮,可以锁定播放器UI交互防止误触。修复了cupertino主题无法导入本地弹幕的bug。尝试修复移动端音量过低的bug。修复了 弹幕告知 功能无效的bug。
1 parent 12e2f8f commit 7a77b14

19 files changed

+482
-111
lines changed

.fvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.35.6

.github/actions/setup-flutter/action.yml

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
name: 'Setup Flutter Environment'
2-
description: '设置 Flutter 开发环境,包括 Java、Flutter 和获取版本信息'
2+
description: '设置 Flutter 开发环境,包括 Java、FVM/Flutter 和获取版本信息'
33
inputs:
4-
flutter-version:
5-
description: 'Flutter 版本'
6-
required: true
7-
default: '3.35.6'
84
java-version:
95
description: 'Java 版本'
106
required: false
@@ -21,13 +17,68 @@ runs:
2117
with:
2218
distribution: 'temurin'
2319
java-version: ${{ inputs.java-version }}
24-
25-
- name: Setup Flutter
26-
uses: subosito/flutter-action@v2
20+
21+
- name: Setup Dart (for FVM)
22+
uses: dart-lang/setup-dart@v1
23+
24+
- name: Cache FVM & Pub cache (Linux/macOS)
25+
if: runner.os != 'Windows'
26+
uses: actions/cache@v4
2727
with:
28-
flutter-version: ${{ inputs.flutter-version }}
29-
cache: true
30-
cache-key: ${{ runner.os }}-flutter-${{ inputs.flutter-version }}-${{ hashFiles('**/pubspec.lock') }}-${{ hashFiles('**/gradle-wrapper.properties') }}-v4
28+
path: |
29+
~/.fvm
30+
~/.pub-cache
31+
key: ${{ runner.os }}-fvm-${{ hashFiles('.fvmrc') }}-${{ hashFiles('**/pubspec.lock') }}-${{ hashFiles('**/gradle-wrapper.properties') }}-v1
32+
restore-keys: |
33+
${{ runner.os }}-fvm-
34+
35+
- name: Cache FVM & Pub cache (Windows)
36+
if: runner.os == 'Windows'
37+
uses: actions/cache@v4
38+
with:
39+
path: |
40+
${{ env.USERPROFILE }}\.fvm
41+
${{ env.LOCALAPPDATA }}\Pub\Cache
42+
key: ${{ runner.os }}-fvm-${{ hashFiles('.fvmrc') }}-${{ hashFiles('**/pubspec.lock') }}-${{ hashFiles('**/gradle-wrapper.properties') }}-v1
43+
restore-keys: |
44+
${{ runner.os }}-fvm-
45+
46+
- name: Install FVM
47+
shell: bash
48+
run: |
49+
dart pub global activate fvm
50+
51+
- name: Install Flutter via FVM (Linux/macOS)
52+
if: runner.os != 'Windows'
53+
shell: bash
54+
run: |
55+
dart pub global run fvm install
56+
dart pub global run fvm use --force
57+
58+
- name: Install Flutter via FVM (Windows)
59+
if: runner.os == 'Windows'
60+
shell: pwsh
61+
run: |
62+
dart pub global run fvm install
63+
dart pub global run fvm use --force
64+
65+
- name: Add Flutter to PATH (Linux/macOS)
66+
if: runner.os != 'Windows'
67+
shell: bash
68+
run: |
69+
echo "$GITHUB_WORKSPACE/.fvm/flutter_sdk/bin" >> "$GITHUB_PATH"
70+
71+
- name: Add Flutter to PATH (Windows)
72+
if: runner.os == 'Windows'
73+
shell: pwsh
74+
run: |
75+
Add-Content -Path $env:GITHUB_PATH -Value "$env:GITHUB_WORKSPACE\.fvm\flutter_sdk\bin"
76+
77+
- name: Disable Flutter analytics
78+
shell: bash
79+
run: |
80+
flutter config --no-analytics
81+
flutter --version
3182
3283
- name: Get app version
3384
id: get_version
@@ -50,4 +101,3 @@ runs:
50101
git config --global core.longpaths true
51102
fi
52103
flutter pub get
53-

.github/workflows/build-android.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@ name: Build Android
22

33
on:
44
workflow_call:
5-
inputs:
6-
flutter-version:
7-
description: 'Flutter 版本'
8-
required: true
9-
type: string
105
secrets:
116
SIGNING_KEY:
127
description: 'Base64 编码的签名密钥'
@@ -59,8 +54,6 @@ jobs:
5954
- name: Setup Flutter Environment
6055
id: setup
6156
uses: ./.github/actions/setup-flutter
62-
with:
63-
flutter-version: ${{ inputs.flutter-version }}
6457

6558
- name: Pre-download Gradle Wrapper
6659
run: |
@@ -83,4 +76,3 @@ jobs:
8376
with:
8477
name: release-Android
8578
path: build/app/outputs/apk/release/NipaPlay-*.apk
86-

.github/workflows/build-ios.yml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@ name: Build iOS
22

33
on:
44
workflow_call:
5-
inputs:
6-
flutter-version:
7-
description: 'Flutter 版本'
8-
required: true
9-
type: string
105
outputs:
116
version:
127
description: '应用版本号'
@@ -47,8 +42,6 @@ jobs:
4742
- name: Setup Flutter Environment
4843
id: setup
4944
uses: ./.github/actions/setup-flutter
50-
with:
51-
flutter-version: ${{ inputs.flutter-version }}
5245

5346
- name: Build iOS IPA
5447
uses: ./.github/actions/build-ios

.github/workflows/build-linux.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@ name: Build Linux
22

33
on:
44
workflow_call:
5-
inputs:
6-
flutter-version:
7-
description: 'Flutter 版本'
8-
required: true
9-
type: string
105
outputs:
116
version:
127
description: '应用版本号'
@@ -35,8 +30,6 @@ jobs:
3530
- name: Setup Flutter Environment
3631
id: setup
3732
uses: ./.github/actions/setup-flutter
38-
with:
39-
flutter-version: ${{ inputs.flutter-version }}
4033

4134
- name: Build Linux Packages
4235
uses: ./.github/actions/build-linux
@@ -52,4 +45,3 @@ jobs:
5245
with:
5346
name: release-Linux-amd64
5447
path: build/linux/
55-

.github/workflows/build-macos.yml

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@ name: Build macOS
22

33
on:
44
workflow_call:
5-
inputs:
6-
flutter-version:
7-
description: 'Flutter 版本'
8-
required: true
9-
type: string
105
secrets:
116
MACOS_CERTIFICATE_BASE64:
127
description: 'macOS Distribution Certificate (Base64)'
@@ -62,8 +57,6 @@ jobs:
6257
- name: Setup Flutter Environment
6358
id: setup
6459
uses: ./.github/actions/setup-flutter
65-
with:
66-
flutter-version: ${{ inputs.flutter-version }}
6760

6861
- name: Build macOS DMG
6962
uses: ./.github/actions/build-macos

.github/workflows/build-windows.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@ name: Build Windows
22

33
on:
44
workflow_call:
5-
inputs:
6-
flutter-version:
7-
description: 'Flutter 版本'
8-
required: true
9-
type: string
105
outputs:
116
version:
127
description: '应用版本号'
@@ -35,8 +30,6 @@ jobs:
3530
- name: Setup Flutter Environment
3631
id: setup
3732
uses: ./.github/actions/setup-flutter
38-
with:
39-
flutter-version: ${{ inputs.flutter-version }}
4033

4134
- name: Build Windows Package
4235
uses: ./.github/actions/build-windows
@@ -51,4 +44,3 @@ jobs:
5144
with:
5245
name: release-Windows-x64
5346
path: build/windows/*
54-

.github/workflows/main.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ concurrency:
1111
group: ${{ github.workflow }}-${{ github.ref_name }}
1212
cancel-in-progress: true
1313

14-
env:
15-
FLUTTER_VERSION: 3.35.6
16-
1714
jobs:
1815
Gatekeeper:
1916
name: Check Commit Message
@@ -41,8 +38,6 @@ jobs:
4138
needs: Gatekeeper
4239
if: needs.Gatekeeper.outputs.triggered == 'true'
4340
uses: ./.github/workflows/build-android.yml
44-
with:
45-
flutter-version: 3.35.6
4641
secrets:
4742
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
4843
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
@@ -54,8 +49,6 @@ jobs:
5449
needs: Gatekeeper
5550
if: needs.Gatekeeper.outputs.triggered == 'true'
5651
uses: ./.github/workflows/build-macos.yml
57-
with:
58-
flutter-version: 3.35.6
5952
secrets:
6053
MACOS_CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE_BASE64 }}
6154
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
@@ -68,16 +61,12 @@ jobs:
6861
needs: Gatekeeper
6962
if: needs.Gatekeeper.outputs.triggered == 'true'
7063
uses: ./.github/workflows/build-windows.yml
71-
with:
72-
flutter-version: 3.35.6
7364

7465
Build-Linux:
7566
name: Build Linux
7667
needs: Gatekeeper
7768
if: needs.Gatekeeper.outputs.triggered == 'true'
7869
uses: ./.github/workflows/build-linux.yml
79-
with:
80-
flutter-version: 3.35.6
8170

8271
Publish:
8372
name: Publish Release

lib/pages/play_video_page.dart

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:async';
12
import 'dart:io';
23
import 'package:flutter/material.dart';
34
import 'package:nipaplay/themes/nipaplay/widgets/video_player_widget.dart';
@@ -14,6 +15,7 @@ import 'package:nipaplay/themes/nipaplay/widgets/anime_info_widget.dart';
1415
import 'package:nipaplay/utils/tab_change_notifier.dart';
1516
import 'package:flutter/gestures.dart';
1617
import 'package:nipaplay/themes/nipaplay/widgets/send_danmaku_button.dart';
18+
import 'package:nipaplay/themes/nipaplay/widgets/lock_controls_button.dart';
1719
import 'package:nipaplay/themes/nipaplay/widgets/skip_button.dart';
1820
import 'package:nipaplay/themes/nipaplay/widgets/send_danmaku_dialog.dart';
1921
import '../player_abstraction/player_abstraction.dart';
@@ -35,11 +37,20 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
3537
bool _isHoveringBackButton = false;
3638
double _horizontalDragDistance = 0.0;
3739
final GlobalKey<SendDanmakuDialogContentState> _danmakuDialogKey = GlobalKey();
40+
bool _isUiLocked = false;
41+
bool _showUiLockButton = false;
42+
Timer? _uiLockButtonTimer;
3843

3944
@override
4045
void initState() {
4146
super.initState();
4247
}
48+
49+
@override
50+
void dispose() {
51+
_uiLockButtonTimer?.cancel();
52+
super.dispose();
53+
}
4354

4455
// 处理系统返回键事件
4556
Future<bool> _handleWillPop() async {
@@ -125,6 +136,39 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
125136
}
126137
}
127138

139+
void _toggleUiLock(VideoPlayerState videoState) {
140+
if (!globals.isPhone) return;
141+
final nextLocked = !_isUiLocked;
142+
_uiLockButtonTimer?.cancel();
143+
setState(() {
144+
_isUiLocked = nextLocked;
145+
_showUiLockButton = nextLocked;
146+
});
147+
videoState.setShowControls(!nextLocked);
148+
149+
if (nextLocked) {
150+
_showUiLockButtonTemporarily();
151+
}
152+
}
153+
154+
void _showUiLockButtonTemporarily([Duration duration = const Duration(seconds: 3)]) {
155+
if (!mounted) return;
156+
if (!globals.isPhone) return;
157+
if (!_isUiLocked) return;
158+
159+
_uiLockButtonTimer?.cancel();
160+
setState(() {
161+
_showUiLockButton = true;
162+
});
163+
_uiLockButtonTimer = Timer(duration, () {
164+
if (!mounted) return;
165+
if (!_isUiLocked) return;
166+
setState(() {
167+
_showUiLockButton = false;
168+
});
169+
});
170+
}
171+
128172
@override
129173
Widget build(BuildContext context) {
130174
final uiThemeProvider = Provider.of<UIThemeProvider>(context);
@@ -159,6 +203,10 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
159203
}
160204

161205
Widget _buildMaterialControls(VideoPlayerState videoState) {
206+
final bool uiLocked = globals.isPhone ? _isUiLocked : false;
207+
final bool showLockButton = globals.isPhone &&
208+
(videoState.showControls || (uiLocked && _showUiLockButton));
209+
162210
return Stack(
163211
children: [
164212
Consumer<VideoPlayerState>(
@@ -243,6 +291,40 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
243291
),
244292
),
245293
const VideoControlsOverlay(),
294+
if (uiLocked)
295+
Positioned.fill(
296+
child: GestureDetector(
297+
behavior: HitTestBehavior.opaque,
298+
onTap: _showUiLockButtonTemporarily,
299+
child: const SizedBox.expand(),
300+
),
301+
),
302+
if (globals.isPhone)
303+
Positioned(
304+
left: 16.0 + (globals.isPhone ? 24.0 : 0.0),
305+
top: 0,
306+
bottom: 0,
307+
child: Center(
308+
child: Transform.translate(
309+
offset: const Offset(0, -90),
310+
child: AnimatedSlide(
311+
duration: const Duration(milliseconds: 150),
312+
offset: Offset(showLockButton ? 0 : -0.1, 0),
313+
child: AnimatedOpacity(
314+
opacity: showLockButton ? 1.0 : 0.0,
315+
duration: const Duration(milliseconds: 150),
316+
child: IgnorePointer(
317+
ignoring: !showLockButton,
318+
child: LockControlsButton(
319+
locked: uiLocked,
320+
onPressed: () => _toggleUiLock(videoState),
321+
),
322+
),
323+
),
324+
),
325+
),
326+
),
327+
),
246328
],
247329
);
248330
}
@@ -305,4 +387,4 @@ class _PlayVideoPageState extends State<PlayVideoPage> {
305387
await videoState.player.playDirectly();
306388
}
307389
}
308-
}
390+
}

0 commit comments

Comments
 (0)