diff --git a/.github/workflows/beta_ci.yml b/.github/workflows/beta_ci.yml
new file mode 100644
index 000000000..e839aca1b
--- /dev/null
+++ b/.github/workflows/beta_ci.yml
@@ -0,0 +1,208 @@
+name: Pilipala Beta
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - "main"
+ paths-ignore:
+ - "**.md"
+ - "**.txt"
+ - ".github/**"
+ - ".idea/**"
+ - "!.github/workflows/**"
+
+jobs:
+ update_version:
+ name: Read and update version
+ runs-on: ubuntu-latest
+
+ outputs:
+ # 定义输出变量 version,以便在其他job中引用
+ new_version: ${{ steps.version.outputs.new_version }}
+ last_commit: ${{ steps.get-last-commit.outputs.last_commit }}
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.ref_name }}
+ fetch-depth: 0
+
+ - name: 获取first parent commit次数
+ id: get-first-parent-commit-count
+ run: |
+ version=$(yq e .version pubspec.yaml | cut -d "+" -f 1)
+ recent_release_tag=$(git tag -l | grep $version | egrep -v "[-|+]" || true)
+ if [[ "x$recent_release_tag" == "x" ]]; then
+ echo "当前版本tag不存在,请手动生成tag."
+ exit 1
+ fi
+ git log --oneline --first-parent $recent_release_tag..HEAD
+ first_parent_commit_count=$(git rev-list --first-parent --count $recent_release_tag..HEAD)
+ echo "count=$first_parent_commit_count" >> $GITHUB_OUTPUT
+
+ - name: 获取最后一次提交
+ id: get-last-commit
+ run: |
+ last_commit=$(git log -1 --pretty="%h %s" --first-parent)
+ echo "last_commit=$last_commit" >> $GITHUB_OUTPUT
+
+ - name: 更新版本号
+ id: version
+ run: |
+ # 读取版本号
+ VERSION=$(yq e .version pubspec.yaml | cut -d "+" -f 1)
+
+ # 获取GitHub Actions的run_number
+ #RUN_NUMBER=${{ github.run_number }}
+
+ # 构建新版本号
+ NEW_VERSION=$VERSION-beta.${{ steps.get-first-parent-commit-count.outputs.count }}
+
+ # 输出新版本号
+ echo "New version: $NEW_VERSION"
+
+ # 设置新版本号为输出变量
+ echo "new_version=$NEW_VERSION" >>$GITHUB_OUTPUT
+
+ android:
+ name: Build CI (Android)
+ needs: update_version
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.ref_name }}
+
+ - name: 构建Java环境
+ uses: actions/setup-java@v3
+ with:
+ distribution: "zulu"
+ java-version: "17"
+ token: ${{secrets.GIT_TOKEN}}
+
+ - name: 检查缓存
+ uses: actions/cache@v2
+ id: cache-flutter
+ with:
+ path: /root/flutter-sdk
+ key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }}
+
+ - name: 安装Flutter
+ if: steps.cache-flutter.outputs.cache-hit != 'true'
+ uses: subosito/flutter-action@v2
+ with:
+ flutter-version: 3.16.5
+ channel: any
+
+ - name: 下载项目依赖
+ run: flutter pub get
+
+ - name: 解码生成 jks
+ run: echo $KEYSTORE_BASE64 | base64 -di > android/app/vvex.jks
+ env:
+ KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
+
+ - name: 更新版本号
+ id: version
+ run: |
+ # 更新pubspec.yaml文件中的版本号
+ sed -i "s/version: .*+/version: ${{ needs.update_version.outputs.new_version }}+/g" pubspec.yaml
+
+ - name: flutter build apk
+ run: flutter build apk --release --split-per-abi
+ env:
+ KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
+ KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
+ KEY_PASSWORD: ${{ secrets.KEY_PASSWORD}}
+
+ - name: 重命名应用
+ run: |
+ for file in build/app/outputs/flutter-apk/app-*.apk; do
+ if [[ $file =~ app-(.?*)release.apk ]]; then
+ new_file_name="build/app/outputs/flutter-apk/Pili-${BASH_REMATCH[1]}v${{ needs.update_version.outputs.new_version }}.apk"
+ mv "$file" "$new_file_name"
+ fi
+ done
+
+ - name: 上传
+ uses: actions/upload-artifact@v3
+ with:
+ name: Pilipala-Beta
+ path: |
+ build/app/outputs/flutter-apk/Pili-*.apk
+
+ iOS:
+ name: Build CI (iOS)
+ needs: update_version
+ runs-on: macos-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.ref_name }}
+
+ - name: 安装Flutter
+ if: steps.cache-flutter.outputs.cache-hit != 'true'
+ uses: subosito/flutter-action@v2.10.0
+ with:
+ cache: true
+ flutter-version: 3.16.5
+
+ - name: 更新版本号
+ id: version
+ run: |
+ # 更新pubspec.yaml文件中的版本号
+ sed -i "" "s/version: .*+/version: ${{ needs.update_version.outputs.new_version }}+/g" pubspec.yaml
+
+ - name: flutter build ipa
+ run: |
+ flutter build ios --release --no-codesign
+ ln -sf ./build/ios/iphoneos Payload
+ zip -r9 app.ipa Payload/runner.app
+
+ - name: 重命名应用
+ run: |
+ DATE=${{ steps.date.outputs.date }}
+ for file in app.ipa; do
+ new_file_name="build/Pili-v${{ needs.update_version.outputs.new_version }}.ipa"
+ mv "$file" "$new_file_name"
+ done
+
+ - name: 上传
+ uses: actions/upload-artifact@v3
+ with:
+ if-no-files-found: error
+ name: Pilipala-Beta
+ path: |
+ build/Pili-*.ipa
+
+ upload:
+ runs-on: ubuntu-latest
+
+ needs:
+ - update_version
+ - android
+ - iOS
+ steps:
+ - uses: actions/download-artifact@v3
+ with:
+ name: Pilipala-Beta
+ path: ./Pilipala-Beta
+
+ - name: 发送到Telegram频道
+ uses: xireiki/channel-post@v1.0.7
+ with:
+ bot_token: ${{ secrets.BOT_TOKEN }}
+ chat_id: ${{ secrets.CHAT_ID }}
+ large_file: true
+ api_id: ${{ secrets.TELEGRAM_API_ID }}
+ api_hash: ${{ secrets.TELEGRAM_API_HASH }}
+ method: sendFile
+ path: Pilipala-Beta/*
+ parse_mode: Markdown
+ context: "*Beta版本: v${{ needs.update_version.outputs.new_version }}*\n更新内容: [${{ needs.update_version.outputs.last_commit }}](${{ github.event.head_commit.url }})"
diff --git a/.github/workflows/main.yml b/.github/workflows/release_ci.yml
similarity index 100%
rename from .github/workflows/main.yml
rename to .github/workflows/release_ci.yml
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index d82845fea..c52d8447a 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -223,6 +223,10 @@
android:pathPattern="/mobile/video/.*" />
+
+
diff --git a/assets/images/video/danmu_close.svg b/assets/images/video/danmu_close.svg
new file mode 100644
index 000000000..9f48027b0
--- /dev/null
+++ b/assets/images/video/danmu_close.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/images/video/danmu_open.svg b/assets/images/video/danmu_open.svg
new file mode 100644
index 000000000..24e8d7a99
--- /dev/null
+++ b/assets/images/video/danmu_open.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/change_log/1.0.20.0303.md b/change_log/1.0.20.0303.md
new file mode 100644
index 000000000..1d8c4e004
--- /dev/null
+++ b/change_log/1.0.20.0303.md
@@ -0,0 +1,31 @@
+## 1.0.20
+
+
+### 功能
++ 评论区增加表情
++ 首页渐变背景开关
++ 媒体库显示「我的订阅」
++ 评论区链接解析
++ 默认启动页设置
+
+### 修复
++ 评论区内容重复
++ pip相关问题
++ 播放多p视频评论不刷新
++ 视频评论翻页重复
+
+### 优化
++ url scheme优化
++ 图片预览放大
++ 图片加载速度
++ 视频评论区复制
++ 全屏显示视频标题
++ 网络异常处理
+
+
+
+
+
+
+更多更新日志可在Github上查看
+问题反馈、功能建议请查看「关于」页面。
diff --git a/change_log/1.0.21.0306.md b/change_log/1.0.21.0306.md
new file mode 100644
index 000000000..3a582dbb1
--- /dev/null
+++ b/change_log/1.0.21.0306.md
@@ -0,0 +1,9 @@
+## 1.0.21
+
+### 修复
++ 推荐视频全屏问题
++ 番剧全屏播放时灰屏问题
++ 评论回调导致页面卡死问题
+
+更多更新日志可在Github上查看
+问题反馈、功能建议请查看「关于」页面。
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 8db59815b..2c1a635ba 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -9,6 +9,7 @@ PODS:
- Flutter
- connectivity_plus (0.0.1):
- Flutter
+ - FlutterMacOS
- ReachabilitySwift
- device_info_plus (0.0.1):
- Flutter
@@ -38,7 +39,7 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- - permission_handler_apple (9.1.1):
+ - permission_handler_apple (9.3.0):
- Flutter
- ReachabilitySwift (5.0.0)
- saver_gallery (0.0.1):
@@ -71,7 +72,7 @@ DEPENDENCIES:
- audio_service (from `.symlinks/plugins/audio_service/ios`)
- audio_session (from `.symlinks/plugins/audio_session/ios`)
- auto_orientation (from `.symlinks/plugins/auto_orientation/ios`)
- - connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
+ - connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- Flutter (from `Flutter`)
- flutter_mailer (from `.symlinks/plugins/flutter_mailer/ios`)
@@ -113,7 +114,7 @@ EXTERNAL SOURCES:
auto_orientation:
:path: ".symlinks/plugins/auto_orientation/ios"
connectivity_plus:
- :path: ".symlinks/plugins/connectivity_plus/ios"
+ :path: ".symlinks/plugins/connectivity_plus/darwin"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
Flutter:
@@ -166,7 +167,7 @@ SPEC CHECKSUMS:
audio_service: f509d65da41b9521a61f1c404dd58651f265a567
audio_session: 4f3e461722055d21515cf3261b64c973c062f345
auto_orientation: 102ed811a5938d52c86520ddd7ecd3a126b5d39d
- connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a
+ connectivity_plus: e2dad488011aeb593e219360e804c43cc1af5770
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
@@ -180,7 +181,7 @@ SPEC CHECKSUMS:
media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
- permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
+ permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
saver_gallery: 2b4e584106fde2407ab51560f3851564963e6b78
screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625
@@ -193,7 +194,7 @@ SPEC CHECKSUMS:
volume_controller: 531ddf792994285c9b17f9d8a7e4dcdd29b3eae9
wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47
webview_cookie_manager: eaf920722b493bd0f7611b5484771ca53fed03f7
- webview_flutter_wkwebview: 2e2d318f21a5e036e2c3f26171342e95908bd60a
+ webview_flutter_wkwebview: 4f3e50f7273d31e5500066ed267e3ae4309c5ae4
PODFILE CHECKSUM: 637cd290bed23275b5f5ffcc7eb1e73d0a5fb2be
diff --git a/lib/common/widgets/network_img_layer.dart b/lib/common/widgets/network_img_layer.dart
index 52c56a8a7..06c359743 100644
--- a/lib/common/widgets/network_img_layer.dart
+++ b/lib/common/widgets/network_img_layer.dart
@@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/utils/extension.dart';
+import 'package:pilipala/utils/global_data.dart';
import '../../utils/storage.dart';
import '../constants.dart';
@@ -32,8 +33,10 @@ class NetworkImgLayer extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ final int defaultImgQuality = GlobalData().imgQuality;
final String imageUrl =
- '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? 100}q.webp';
+ '${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? defaultImgQuality}q.webp';
+ print(imageUrl);
int? memCacheWidth, memCacheHeight;
double aspectRatio = (width / height).toDouble();
@@ -81,7 +84,7 @@ class NetworkImgLayer extends StatelessWidget {
fadeOutDuration ?? const Duration(milliseconds: 120),
fadeInDuration:
fadeInDuration ?? const Duration(milliseconds: 120),
- filterQuality: FilterQuality.high,
+ filterQuality: FilterQuality.low,
errorWidget: (BuildContext context, String url, Object error) =>
placeholder(context),
placeholder: (BuildContext context, String url) =>
diff --git a/lib/common/widgets/video_card_h.dart b/lib/common/widgets/video_card_h.dart
index c78643db0..99059a9e8 100644
--- a/lib/common/widgets/video_card_h.dart
+++ b/lib/common/widgets/video_card_h.dart
@@ -38,6 +38,10 @@ class VideoCardH extends StatelessWidget {
Widget build(BuildContext context) {
final int aid = videoItem.aid;
final String bvid = videoItem.bvid;
+ String type = 'video';
+ try {
+ type = videoItem.type;
+ } catch (_) {}
final String heroTag = Utils.makeHeroTag(aid);
return GestureDetector(
onLongPress: () {
@@ -53,6 +57,10 @@ class VideoCardH extends StatelessWidget {
child: InkWell(
onTap: () async {
try {
+ if (type == 'ketang') {
+ SmartDialog.showToast('课堂视频暂不支持播放');
+ return;
+ }
final int cid =
videoItem.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid);
Get.toNamed('/video?bvid=$bvid&cid=$cid',
@@ -95,12 +103,20 @@ class VideoCardH extends StatelessWidget {
height: maxHeight,
),
),
- PBadge(
- text: Utils.timeFormat(videoItem.duration!),
- right: 6.0,
- bottom: 6.0,
- type: 'gray',
- ),
+ if (videoItem.duration != 0)
+ PBadge(
+ text: Utils.timeFormat(videoItem.duration!),
+ right: 6.0,
+ bottom: 6.0,
+ type: 'gray',
+ ),
+ if (type != 'video')
+ PBadge(
+ text: type,
+ left: 6.0,
+ bottom: 6.0,
+ type: 'primary',
+ ),
// if (videoItem.rcmdReason != null &&
// videoItem.rcmdReason.content != '')
// pBadge(videoItem.rcmdReason.content, context,
diff --git a/lib/common/widgets/video_card_v.dart b/lib/common/widgets/video_card_v.dart
index 43dd05caa..0d96f7b77 100644
--- a/lib/common/widgets/video_card_v.dart
+++ b/lib/common/widgets/video_card_v.dart
@@ -231,6 +231,7 @@ class VideoContent extends StatelessWidget {
const SizedBox(height: 2),
VideoStat(
videoItem: videoItem,
+ crossAxisCount: crossAxisCount,
),
],
if (crossAxisCount == 1) const SizedBox(height: 4),
@@ -294,6 +295,7 @@ class VideoContent extends StatelessWidget {
),
VideoStat(
videoItem: videoItem,
+ crossAxisCount: crossAxisCount,
),
const Spacer(),
],
@@ -317,10 +319,12 @@ class VideoContent extends StatelessWidget {
class VideoStat extends StatelessWidget {
final dynamic videoItem;
+ final int crossAxisCount;
const VideoStat({
Key? key,
required this.videoItem,
+ required this.crossAxisCount,
}) : super(key: key);
@override
@@ -337,7 +341,7 @@ class VideoStat extends StatelessWidget {
danmu: videoItem.stat.danmu,
),
if (videoItem is RecVideoItemModel) ...[
- const Spacer(),
+ crossAxisCount > 1 ? const Spacer() : const SizedBox(width: 8),
RichText(
maxLines: 1,
text: TextSpan(
diff --git a/lib/http/api.dart b/lib/http/api.dart
index 736030b2e..445f61028 100644
--- a/lib/http/api.dart
+++ b/lib/http/api.dart
@@ -484,9 +484,26 @@ class Api {
/// 激活buvid3
static const activateBuvidApi = '/x/internal/gaia-gateway/ExClimbWuzhi';
+ /// 获取字幕配置
+ static const getSubtitleConfig = '/x/player/v2';
+
/// 我的订阅
static const userSubFolder = '/x/v3/fav/folder/collected/list';
/// 我的订阅详情
static const userSubFolderDetail = '/x/space/fav/season/list';
+
+ /// 表情
+ static const emojiList = '/x/emote/user/panel/web';
+
+ /// 已读标记
+ static const String ackSessionMsg =
+ '${HttpString.tUrl}/session_svr/v1/session_svr/update_ack';
+
+ /// 发送私信
+ static const String sendMsg = '${HttpString.tUrl}/web_im/v1/web_im/send_msg';
+
+ /// 排行榜
+ static const String getRankApi = "/x/web-interface/ranking/v2";
+
}
diff --git a/lib/http/interceptor.dart b/lib/http/interceptor.dart
index 362ff17ad..a53592830 100644
--- a/lib/http/interceptor.dart
+++ b/lib/http/interceptor.dart
@@ -45,10 +45,13 @@ class ApiInterceptor extends Interceptor {
void onError(DioException err, ErrorInterceptorHandler handler) async {
// 处理网络请求错误
// handler.next(err);
- SmartDialog.showToast(
- await dioError(err),
- displayType: SmartToastType.onlyRefresh,
- );
+ String url = err.requestOptions.uri.toString();
+ if (!url.contains('heartBeat')) {
+ SmartDialog.showToast(
+ await dioError(err),
+ displayType: SmartToastType.onlyRefresh,
+ );
+ }
super.onError(err, handler);
}
@@ -75,23 +78,24 @@ class ApiInterceptor extends Interceptor {
}
static Future checkConnect() async {
- final ConnectivityResult connectivityResult =
+ final List connectivityResult =
await Connectivity().checkConnectivity();
- switch (connectivityResult) {
- case ConnectivityResult.mobile:
- return '正在使用移动流量';
- case ConnectivityResult.wifi:
- return '正在使用wifi';
- case ConnectivityResult.ethernet:
- return '正在使用局域网';
- case ConnectivityResult.vpn:
- return '正在使用代理网络';
- case ConnectivityResult.other:
- return '正在使用其他网络';
- case ConnectivityResult.none:
- return '未连接到任何网络';
- default:
- return '';
+ if (connectivityResult.contains(ConnectivityResult.mobile)) {
+ return '正在使用移动流量';
+ } else if (connectivityResult.contains(ConnectivityResult.wifi)) {
+ return '正在使用wifi';
+ } else if (connectivityResult.contains(ConnectivityResult.ethernet)) {
+ return '正在使用局域网';
+ } else if (connectivityResult.contains(ConnectivityResult.vpn)) {
+ return '正在使用代理网络';
+ } else if (connectivityResult.contains(ConnectivityResult.bluetooth)) {
+ return '正在使用蓝牙网络';
+ } else if (connectivityResult.contains(ConnectivityResult.other)) {
+ return '正在使用其他网络';
+ } else if (connectivityResult.contains(ConnectivityResult.none)) {
+ return '未连接到任何网络';
+ } else {
+ return '';
}
}
}
diff --git a/lib/http/msg.dart b/lib/http/msg.dart
index 70af5b559..d1d319588 100644
--- a/lib/http/msg.dart
+++ b/lib/http/msg.dart
@@ -1,3 +1,4 @@
+import 'dart:math';
import '../models/msg/account.dart';
import '../models/msg/session.dart';
import '../utils/wbi_sign.dart';
@@ -22,14 +23,22 @@ class MsgHttp {
Map signParams = await WbiSign().makSign(params);
var res = await Request().get(Api.sessionList, data: signParams);
if (res.data['code'] == 0) {
- return {
- 'status': true,
- 'data': SessionDataModel.fromJson(res.data['data']),
- };
+ try {
+ return {
+ 'status': true,
+ 'data': SessionDataModel.fromJson(res.data['data']),
+ };
+ } catch (err) {
+ return {
+ 'status': false,
+ 'data': [],
+ 'msg': err.toString(),
+ };
+ }
} else {
return {
'status': false,
- 'date': [],
+ 'data': [],
'msg': res.data['message'],
};
}
@@ -42,12 +51,16 @@ class MsgHttp {
'mobi_app': 'web',
});
if (res.data['code'] == 0) {
- return {
- 'status': true,
- 'data': res.data['data']
- .map((e) => AccountListModel.fromJson(e))
- .toList(),
- };
+ try {
+ return {
+ 'status': true,
+ 'data': res.data['data']
+ .map((e) => AccountListModel.fromJson(e))
+ .toList(),
+ };
+ } catch (err) {
+ print('err🔟: $err');
+ }
} else {
return {
'status': false,
@@ -86,4 +99,125 @@ class MsgHttp {
};
}
}
+
+ // 消息标记已读
+ static Future ackSessionMsg({
+ int? talkerId,
+ int? ackSeqno,
+ }) async {
+ String csrf = await Request.getCsrf();
+ Map params = await WbiSign().makSign({
+ 'talker_id': talkerId,
+ 'session_type': 1,
+ 'ack_seqno': ackSeqno,
+ 'build': 0,
+ 'mobi_app': 'web',
+ 'csrf_token': csrf,
+ 'csrf': csrf
+ });
+ var res = await Request().get(Api.ackSessionMsg, data: params);
+ if (res.data['code'] == 0) {
+ return {
+ 'status': true,
+ 'data': res.data['data'],
+ };
+ } else {
+ return {
+ 'status': false,
+ 'date': [],
+ 'msg': "message: ${res.data['message']},"
+ " msg: ${res.data['msg']},"
+ " code: ${res.data['code']}",
+ };
+ }
+ }
+
+ // 发送私信
+ static Future sendMsg({
+ int? senderUid,
+ int? receiverId,
+ int? receiverType,
+ int? msgType,
+ dynamic content,
+ }) async {
+ String csrf = await Request.getCsrf();
+ Map params = await WbiSign().makSign({
+ 'msg[sender_uid]': senderUid,
+ 'msg[receiver_id]': receiverId,
+ 'msg[receiver_type]': receiverType ?? 1,
+ 'msg[msg_type]': msgType ?? 1,
+ 'msg[msg_status]': 0,
+ 'msg[dev_id]': getDevId(),
+ 'msg[timestamp]': DateTime.now().millisecondsSinceEpoch ~/ 1000,
+ 'msg[new_face_version]': 0,
+ 'msg[content]': content,
+ 'from_firework': 0,
+ 'build': 0,
+ 'mobi_app': 'web',
+ 'csrf_token': csrf,
+ 'csrf': csrf,
+ });
+ var res =
+ await Request().post(Api.sendMsg, queryParameters: {
+ ...params,
+ 'csrf_token': csrf,
+ 'csrf': csrf,
+ }, data: {
+ 'w_sender_uid': params['msg[sender_uid]'],
+ 'w_receiver_id': params['msg[receiver_id]'],
+ 'w_dev_id': params['msg[dev_id]'],
+ 'w_rid': params['w_rid'],
+ 'wts': params['wts'],
+ 'csrf_token': csrf,
+ 'csrf': csrf,
+ });
+ if (res.data['code'] == 0) {
+ return {
+ 'status': true,
+ 'data': res.data['data'],
+ };
+ } else {
+ return {
+ 'status': false,
+ 'date': [],
+ 'msg': "message: ${res.data['message']},"
+ " msg: ${res.data['msg']},"
+ " code: ${res.data['code']}",
+ };
+ }
+ }
+
+ static String getDevId() {
+ final List b = [
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F'
+ ];
+ final List s = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".split('');
+ for (int i = 0; i < s.length; i++) {
+ if ('-' == s[i] || '4' == s[i]) {
+ continue;
+ }
+ final int randomInt = Random().nextInt(16);
+ if ('x' == s[i]) {
+ s[i] = b[randomInt];
+ } else {
+ s[i] = b[3 & randomInt | 8];
+ }
+ }
+ return s.join();
+ }
}
diff --git a/lib/http/reply.dart b/lib/http/reply.dart
index fab433fc7..f080ed514 100644
--- a/lib/http/reply.dart
+++ b/lib/http/reply.dart
@@ -1,4 +1,5 @@
import '../models/video/reply/data.dart';
+import '../models/video/reply/emote.dart';
import 'api.dart';
import 'init.dart';
@@ -100,4 +101,23 @@ class ReplyHttp {
};
}
}
+
+ static Future getEmoteList({String? business}) async {
+ var res = await Request().get(Api.emojiList, data: {
+ 'business': business ?? 'reply',
+ 'web_location': '333.1245',
+ });
+ if (res.data['code'] == 0) {
+ return {
+ 'status': true,
+ 'data': EmoteModelData.fromJson(res.data['data']),
+ };
+ } else {
+ return {
+ 'status': false,
+ 'date': [],
+ 'msg': res.data['message'],
+ };
+ }
+ }
}
diff --git a/lib/http/video.dart b/lib/http/video.dart
index 30df62c3e..d43656b28 100644
--- a/lib/http/video.dart
+++ b/lib/http/video.dart
@@ -8,9 +8,11 @@ import '../models/model_rec_video_item.dart';
import '../models/user/fav_folder.dart';
import '../models/video/ai.dart';
import '../models/video/play/url.dart';
+import '../models/video/subTitile/result.dart';
import '../models/video_detail_res.dart';
import '../utils/recommend_filter.dart';
import '../utils/storage.dart';
+import '../utils/subtitle.dart';
import '../utils/wbi_sign.dart';
import 'api.dart';
import 'init.dart';
@@ -475,4 +477,54 @@ class VideoHttp {
return {'status': false, 'data': []};
}
}
+
+ static Future getSubtitle({int? cid, String? bvid}) async {
+ var res = await Request().get(Api.getSubtitleConfig, data: {
+ 'cid': cid,
+ 'bvid': bvid,
+ });
+ try {
+ if (res.data['code'] == 0) {
+ return {
+ 'status': true,
+ 'data': SubTitlteModel.fromJson(res.data['data']),
+ };
+ } else {
+ return {'status': false, 'data': [], 'msg': res.data['msg']};
+ }
+ } catch (err) {
+ print(err);
+ }
+ }
+
+ // 视频排行
+ static Future getRankVideoList(int rid) async {
+ try {
+ var rankApi = "${Api.getRankApi}?rid=$rid&type=all";
+ var res = await Request().get(rankApi);
+ if (res.data['code'] == 0) {
+ List list = [];
+ List blackMidsList =
+ setting.get(SettingBoxKey.blackMidsList, defaultValue: [-1]);
+ for (var i in res.data['data']['list']) {
+ if (!blackMidsList.contains(i['owner']['mid'])) {
+ list.add(HotVideoItemModel.fromJson(i));
+ }
+ }
+ return {'status': true, 'data': list};
+ } else {
+ return {'status': false, 'data': [], 'msg': res.data['message']};
+ }
+ } catch (err) {
+ return {'status': false, 'data': [], 'msg': err};
+ }
+ }
+
+ // 获取字幕内容
+ static Future