Merge remote-tracking branch 'upstream/main'

This commit is contained in:
orz12
2024-01-27 11:14:48 +08:00
11 changed files with 57 additions and 302 deletions

View File

@@ -8,6 +8,7 @@ import 'package:dio/io.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart'; import 'package:dio_cookie_manager/dio_cookie_manager.dart';
// import 'package:dio_http2_adapter/dio_http2_adapter.dart'; // import 'package:dio_http2_adapter/dio_http2_adapter.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:pilipala/utils/id_utils.dart';
import '../utils/storage.dart'; import '../utils/storage.dart';
import '../utils/utils.dart'; import '../utils/utils.dart';
import 'constants.dart'; import 'constants.dart';
@@ -79,10 +80,11 @@ class Request {
static setOptionsHeaders(userInfo, bool status) { static setOptionsHeaders(userInfo, bool status) {
if (status) { if (status) {
dio.options.headers['x-bili-mid'] = userInfo.mid.toString(); dio.options.headers['x-bili-mid'] = userInfo.mid.toString();
dio.options.headers['x-bili-aurora-eid'] =
IdUtils.genAuroraEid(userInfo.mid);
} }
dio.options.headers['env'] = 'prod'; dio.options.headers['env'] = 'prod';
dio.options.headers['app-key'] = 'android64'; dio.options.headers['app-key'] = 'android64';
dio.options.headers['x-bili-aurora-eid'] = 'UlMFQVcABlAH';
dio.options.headers['x-bili-aurora-zone'] = 'sh001'; dio.options.headers['x-bili-aurora-zone'] = 'sh001';
dio.options.headers['referer'] = 'https://www.bilibili.com/'; dio.options.headers['referer'] = 'https://www.bilibili.com/';
} }

View File

@@ -1,8 +1,3 @@
import 'package:hive/hive.dart';
part 'result.g.dart';
@HiveType(typeId: 0)
class RecVideoItemAppModel { class RecVideoItemAppModel {
RecVideoItemAppModel({ RecVideoItemAppModel({
this.id, this.id,
@@ -27,47 +22,27 @@ class RecVideoItemAppModel {
this.adInfo, this.adInfo,
}); });
@HiveField(0)
int? id; int? id;
@HiveField(1)
int? aid; int? aid;
@HiveField(2)
String? bvid; String? bvid;
@HiveField(3)
int? cid; int? cid;
@HiveField(4)
String? pic; String? pic;
@HiveField(5)
RcmdStat? stat; RcmdStat? stat;
@HiveField(6)
int? duration; int? duration;
@HiveField(7)
String? title; String? title;
@HiveField(8)
int? isFollowed; int? isFollowed;
@HiveField(9)
RcmdOwner? owner; RcmdOwner? owner;
@HiveField(10)
RcmdReason? rcmdReason; RcmdReason? rcmdReason;
@HiveField(11)
String? goto; String? goto;
@HiveField(12)
int? param; int? param;
@HiveField(13)
String? uri; String? uri;
@HiveField(14)
String? talkBack; String? talkBack;
// 番剧 // 番剧
@HiveField(15)
String? bangumiView; String? bangumiView;
@HiveField(16)
String? bangumiFollow; String? bangumiFollow;
@HiveField(17)
String? bangumiBadge; String? bangumiBadge;
@HiveField(18)
String? cardType; String? cardType;
@HiveField(19)
Map? adInfo; Map? adInfo;
RecVideoItemAppModel.fromJson(Map<String, dynamic> json) { RecVideoItemAppModel.fromJson(Map<String, dynamic> json) {
@@ -116,18 +91,14 @@ class RecVideoItemAppModel {
} }
} }
@HiveType(typeId: 1)
class RcmdStat { class RcmdStat {
RcmdStat({ RcmdStat({
this.view, this.view,
this.like, this.like,
this.danmu, this.danmu,
}); });
@HiveField(0)
String? view; String? view;
@HiveField(1)
String? like; String? like;
@HiveField(2)
String? danmu; String? danmu;
RcmdStat.fromJson(Map<String, dynamic> json) { RcmdStat.fromJson(Map<String, dynamic> json) {
@@ -136,13 +107,10 @@ class RcmdStat {
} }
} }
@HiveType(typeId: 2)
class RcmdOwner { class RcmdOwner {
RcmdOwner({this.name, this.mid}); RcmdOwner({this.name, this.mid});
@HiveField(0)
String? name; String? name;
@HiveField(1)
int? mid; int? mid;
RcmdOwner.fromJson(Map<String, dynamic> json) { RcmdOwner.fromJson(Map<String, dynamic> json) {
@@ -155,13 +123,11 @@ class RcmdOwner {
} }
} }
@HiveType(typeId: 8)
class RcmdReason { class RcmdReason {
RcmdReason({ RcmdReason({
this.content, this.content,
}); });
@HiveField(0)
String? content; String? content;
RcmdReason.fromJson(Map<String, dynamic> json) { RcmdReason.fromJson(Map<String, dynamic> json) {

View File

@@ -1,209 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'result.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class RecVideoItemAppModelAdapter extends TypeAdapter<RecVideoItemAppModel> {
@override
final int typeId = 0;
@override
RecVideoItemAppModel read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return RecVideoItemAppModel(
id: fields[0] as int?,
aid: fields[1] as int?,
bvid: fields[2] as String?,
cid: fields[3] as int?,
pic: fields[4] as String?,
stat: fields[5] as RcmdStat?,
duration: fields[6] as int?,
title: fields[7] as String?,
isFollowed: fields[8] as int?,
owner: fields[9] as RcmdOwner?,
rcmdReason: fields[10] as RcmdReason?,
goto: fields[11] as String?,
param: fields[12] as int?,
uri: fields[13] as String?,
talkBack: fields[14] as String?,
bangumiView: fields[15] as String?,
bangumiFollow: fields[16] as String?,
bangumiBadge: fields[17] as String?,
cardType: fields[18] as String?,
adInfo: (fields[19] as Map?)?.cast<dynamic, dynamic>(),
);
}
@override
void write(BinaryWriter writer, RecVideoItemAppModel obj) {
writer
..writeByte(20)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.aid)
..writeByte(2)
..write(obj.bvid)
..writeByte(3)
..write(obj.cid)
..writeByte(4)
..write(obj.pic)
..writeByte(5)
..write(obj.stat)
..writeByte(6)
..write(obj.duration)
..writeByte(7)
..write(obj.title)
..writeByte(8)
..write(obj.isFollowed)
..writeByte(9)
..write(obj.owner)
..writeByte(10)
..write(obj.rcmdReason)
..writeByte(11)
..write(obj.goto)
..writeByte(12)
..write(obj.param)
..writeByte(13)
..write(obj.uri)
..writeByte(14)
..write(obj.talkBack)
..writeByte(15)
..write(obj.bangumiView)
..writeByte(16)
..write(obj.bangumiFollow)
..writeByte(17)
..write(obj.bangumiBadge)
..writeByte(18)
..write(obj.cardType)
..writeByte(19)
..write(obj.adInfo);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is RecVideoItemAppModelAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class RcmdStatAdapter extends TypeAdapter<RcmdStat> {
@override
final int typeId = 1;
@override
RcmdStat read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return RcmdStat(
view: fields[0] as String?,
like: fields[1] as String?,
danmu: fields[2] as String?,
);
}
@override
void write(BinaryWriter writer, RcmdStat obj) {
writer
..writeByte(3)
..writeByte(0)
..write(obj.view)
..writeByte(1)
..write(obj.like)
..writeByte(2)
..write(obj.danmu);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is RcmdStatAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class RcmdOwnerAdapter extends TypeAdapter<RcmdOwner> {
@override
final int typeId = 2;
@override
RcmdOwner read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return RcmdOwner(
name: fields[0] as String?,
mid: fields[1] as int?,
);
}
@override
void write(BinaryWriter writer, RcmdOwner obj) {
writer
..writeByte(2)
..writeByte(0)
..write(obj.name)
..writeByte(1)
..write(obj.mid);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is RcmdOwnerAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class RcmdReasonAdapter extends TypeAdapter<RcmdReason> {
@override
final int typeId = 8;
@override
RcmdReason read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return RcmdReason(
content: fields[0] as String?,
);
}
@override
void write(BinaryWriter writer, RcmdReason obj) {
writer
..writeByte(1)
..writeByte(0)
..write(obj.content);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is RcmdReasonAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -5,6 +5,7 @@ import 'package:get/get.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:pilipala/models/common/tab_type.dart'; import 'package:pilipala/models/common/tab_type.dart';
import 'package:pilipala/utils/storage.dart'; import 'package:pilipala/utils/storage.dart';
import '../../http/index.dart';
class HomeController extends GetxController with GetTickerProviderStateMixin { class HomeController extends GetxController with GetTickerProviderStateMixin {
bool flag = false; bool flag = false;
@@ -24,6 +25,7 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
late bool hideSearchBar; late bool hideSearchBar;
late List defaultTabs; late List defaultTabs;
late List<String> tabbarSort; late List<String> tabbarSort;
RxString defaultSearch = ''.obs;
@override @override
void onInit() { void onInit() {
@@ -35,6 +37,9 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
setTabConfig(); setTabConfig();
hideSearchBar = hideSearchBar =
setting.get(SettingBoxKey.hideSearchBar, defaultValue: true); setting.get(SettingBoxKey.hideSearchBar, defaultValue: true);
if (setting.get(SettingBoxKey.enableSearchWord, defaultValue: true)) {
searchDefault();
}
} }
void onRefresh() { void onRefresh() {
@@ -94,4 +99,11 @@ class HomeController extends GetxController with GetTickerProviderStateMixin {
} }
}); });
} }
void searchDefault() async {
var res = await Request().get(Api.searchDefault);
if (res.data['code'] == 0) {
defaultSearch.value = res.data['data']['name'];
}
}
} }

View File

@@ -5,7 +5,6 @@ import 'package:flutter/services.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:pilipala/common/widgets/network_img_layer.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart';
import 'package:pilipala/pages/mine/index.dart'; import 'package:pilipala/pages/mine/index.dart';
import 'package:pilipala/pages/search/index.dart';
import 'package:pilipala/utils/feed_back.dart'; import 'package:pilipala/utils/feed_back.dart';
import './controller.dart'; import './controller.dart';
@@ -144,6 +143,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
padding: EdgeInsets.fromLTRB(14, top + 6, 14, 0), padding: EdgeInsets.fromLTRB(14, top + 6, 14, 0),
child: UserInfoWidget( child: UserInfoWidget(
top: top, top: top,
ctr: ctr,
userLogin: isUserLoggedIn, userLogin: isUserLoggedIn,
userFace: ctr?.userFace.value, userFace: ctr?.userFace.value,
callback: () => callback!(), callback: () => callback!(),
@@ -162,18 +162,20 @@ class UserInfoWidget extends StatelessWidget {
required this.userLogin, required this.userLogin,
required this.userFace, required this.userFace,
required this.callback, required this.callback,
required this.ctr,
}) : super(key: key); }) : super(key: key);
final double top; final double top;
final RxBool userLogin; final RxBool userLogin;
final String? userFace; final String? userFace;
final VoidCallback? callback; final VoidCallback? callback;
final HomeController? ctr;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Row( return Row(
children: [ children: [
const SearchBar(), SearchBar(ctr: ctr),
if (userLogin.value) ...[ if (userLogin.value) ...[
const SizedBox(width: 4), const SizedBox(width: 4),
ClipRect( ClipRect(
@@ -335,11 +337,15 @@ class CustomChip extends StatelessWidget {
} }
class SearchBar extends StatelessWidget { class SearchBar extends StatelessWidget {
const SearchBar({super.key}); const SearchBar({
Key? key,
required this.ctr,
}) : super(key: key);
final HomeController? ctr;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final SSearchController searchController = Get.put(SSearchController());
final ColorScheme colorScheme = Theme.of(context).colorScheme; final ColorScheme colorScheme = Theme.of(context).colorScheme;
return Expanded( return Expanded(
child: Container( child: Container(
@@ -353,7 +359,10 @@ class SearchBar extends StatelessWidget {
color: colorScheme.onSecondaryContainer.withOpacity(0.05), color: colorScheme.onSecondaryContainer.withOpacity(0.05),
child: InkWell( child: InkWell(
splashColor: colorScheme.primaryContainer.withOpacity(0.3), splashColor: colorScheme.primaryContainer.withOpacity(0.3),
onTap: () => Get.toNamed('/search'), onTap: () => Get.toNamed(
'/search',
parameters: {'hintText': ctr!.defaultSearch.value},
),
child: Row( child: Row(
children: [ children: [
const SizedBox(width: 14), const SizedBox(width: 14),
@@ -362,14 +371,12 @@ class SearchBar extends StatelessWidget {
color: colorScheme.onSecondaryContainer, color: colorScheme.onSecondaryContainer,
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Obx(
child: Obx( () => Text(
() => Text( ctr!.defaultSearch.value,
searchController.defaultSearch.value, maxLines: 1,
maxLines: 1, overflow: TextOverflow.ellipsis,
overflow: TextOverflow.ellipsis, style: TextStyle(color: colorScheme.outline),
style: TextStyle(color: colorScheme.outline),
),
), ),
), ),
], ],

View File

@@ -13,7 +13,6 @@ class RcmdController extends GetxController {
// RxList<RecVideoItemModel> webVideoList = <RecVideoItemModel>[].obs; // RxList<RecVideoItemModel> webVideoList = <RecVideoItemModel>[].obs;
bool isLoadingMore = true; bool isLoadingMore = true;
OverlayEntry? popupDialog; OverlayEntry? popupDialog;
Box recVideo = GStrorage.recVideo;
Box setting = GStrorage.setting; Box setting = GStrorage.setting;
RxInt crossAxisCount = 2.obs; RxInt crossAxisCount = 2.obs;
late bool enableSaveLastData; late bool enableSaveLastData;
@@ -23,15 +22,6 @@ class RcmdController extends GetxController {
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
// 读取app端缓存内容
// if (recVideo.get('cacheList') != null &&
// recVideo.get('cacheList').isNotEmpty) {
// List<RecVideoItemAppModel> list = [];
// for (var i in recVideo.get('cacheList')) {
// list.add(i);
// }
// videoList.value = list;
// }
enableSaveLastData = enableSaveLastData =
setting.get(SettingBoxKey.enableSaveLastData, defaultValue: false); setting.get(SettingBoxKey.enableSaveLastData, defaultValue: false);
defaultRcmdType = defaultRcmdType =
@@ -82,10 +72,6 @@ class RcmdController extends GetxController {
} else if (type == 'onLoad') { } else if (type == 'onLoad') {
videoList.addAll(res['data']); videoList.addAll(res['data']);
} }
// 目前仅支持app端系列保存缓存
if (defaultRcmdType != 'web') {
recVideo.put('cacheList', res['data']);
}
_currentPage += 1; _currentPage += 1;
// 若videoList数量太小可能会影响翻页此时再次请求 // 若videoList数量太小可能会影响翻页此时再次请求
// 为避免请求到的数据太少时还在反复请求要求本次返回数据大于1条才触发 // 为避免请求到的数据太少时还在反复请求要求本次返回数据大于1条才触发

View File

@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart'; import 'package:get/get_rx/src/rx_workers/utils/debouncer.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:pilipala/http/index.dart';
import 'package:pilipala/http/search.dart'; import 'package:pilipala/http/search.dart';
import 'package:pilipala/models/search/hot.dart'; import 'package:pilipala/models/search/hot.dart';
import 'package:pilipala/models/search/suggest.dart'; import 'package:pilipala/models/search/suggest.dart';
@@ -27,9 +26,6 @@ class SSearchController extends GetxController {
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
if (setting.get(SettingBoxKey.enableSearchWord, defaultValue: true)) {
searchDefault();
}
// 其他页面跳转过来 // 其他页面跳转过来
if (Get.parameters.keys.isNotEmpty) { if (Get.parameters.keys.isNotEmpty) {
if (Get.parameters['keyword'] != null) { if (Get.parameters['keyword'] != null) {
@@ -130,12 +126,4 @@ class SSearchController extends GetxController {
historyList.refresh(); historyList.refresh();
histiryWord.put('cacheList', []); histiryWord.put('cacheList', []);
} }
void searchDefault() async {
var res = await Request().get(Api.searchDefault);
if (res.data['code'] == 0) {
searchKeyWord.value =
hintText = defaultSearch.value = res.data['data']['name'];
}
}
} }

View File

@@ -90,7 +90,7 @@ class SearchVideoPanel extends StatelessWidget {
style: ButtonStyle( style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.zero), padding: MaterialStateProperty.all(EdgeInsets.zero),
), ),
onPressed: () => controller.onShowFilterDialog(), onPressed: () => controller.onShowFilterDialog(ctr),
icon: Icon( icon: Icon(
Icons.filter_list_outlined, Icons.filter_list_outlined,
size: 18, size: 18,
@@ -175,7 +175,7 @@ class VideoPanelController extends GetxController {
super.onInit(); super.onInit();
} }
onShowFilterDialog() { onShowFilterDialog(searchPanelCtr) {
SmartDialog.show( SmartDialog.show(
animationType: SmartAnimationType.centerFade_otherSlide, animationType: SmartAnimationType.centerFade_otherSlide,
builder: (BuildContext context) { builder: (BuildContext context) {
@@ -199,7 +199,8 @@ class VideoPanelController extends GetxController {
SmartDialog.dismiss(); SmartDialog.dismiss();
SmartDialog.showToast("${i['label']}」的筛选结果"); SmartDialog.showToast("${i['label']}」的筛选结果");
SearchPanelController ctr = SearchPanelController ctr =
Get.find<SearchPanelController>(tag: 'video'); Get.find<SearchPanelController>(
tag: 'video${searchPanelCtr.keyword!}');
ctr.duration.value = i['value']; ctr.duration.value = i['value'];
SmartDialog.showLoading(msg: 'loading'); SmartDialog.showLoading(msg: 'loading');
await ctr.onRefresh(); await ctr.onRefresh();

View File

@@ -86,7 +86,8 @@ class _SearchResultPageState extends State<SearchResultPage>
onTap: (index) { onTap: (index) {
if (index == _searchResultController!.tabIndex) { if (index == _searchResultController!.tabIndex) {
Get.find<SearchPanelController>( Get.find<SearchPanelController>(
tag: SearchType.values[index].type) tag: SearchType.values[index].type +
_searchResultController!.keyword!)
.animateToTop(); .animateToTop();
} }

View File

@@ -1,5 +1,6 @@
// ignore_for_file: constant_identifier_names // ignore_for_file: constant_identifier_names
import 'dart:convert';
import 'dart:math'; import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -72,4 +73,19 @@ class IdUtils {
} }
return result; return result;
} }
// eid生成
static String? genAuroraEid(int uid) {
if (uid == 0) {
return null;
}
String uidString = uid.toString();
List<int> resultBytes = List.generate(
uidString.length,
(i) => uidString.codeUnitAt(i) ^ "ad1va46a7lza".codeUnitAt(i % 12),
);
String auroraEid = base64Url.encode(resultBytes);
auroraEid = auroraEid.replaceAll(RegExp(r'=*$', multiLine: true), '');
return auroraEid;
}
} }

View File

@@ -3,13 +3,11 @@ import 'dart:io';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:pilipala/models/home/rcmd/result.dart';
import 'package:pilipala/models/model_owner.dart'; import 'package:pilipala/models/model_owner.dart';
import 'package:pilipala/models/search/hot.dart'; import 'package:pilipala/models/search/hot.dart';
import 'package:pilipala/models/user/info.dart'; import 'package:pilipala/models/user/info.dart';
class GStrorage { class GStrorage {
static late final Box<dynamic> recVideo;
static late final Box<dynamic> userInfo; static late final Box<dynamic> userInfo;
static late final Box<dynamic> historyword; static late final Box<dynamic> historyword;
static late final Box<dynamic> localCache; static late final Box<dynamic> localCache;
@@ -21,13 +19,6 @@ class GStrorage {
final String path = dir.path; final String path = dir.path;
await Hive.initFlutter('$path/hive'); await Hive.initFlutter('$path/hive');
regAdapter(); regAdapter();
// 首页推荐视频
recVideo = await Hive.openBox(
'recVideo',
compactionStrategy: (int entries, int deletedEntries) {
return deletedEntries > 12;
},
);
// 登录用户信息 // 登录用户信息
userInfo = await Hive.openBox( userInfo = await Hive.openBox(
'userInfo', 'userInfo',
@@ -54,10 +45,6 @@ class GStrorage {
} }
static void regAdapter() { static void regAdapter() {
Hive.registerAdapter(RecVideoItemAppModelAdapter());
Hive.registerAdapter(RcmdReasonAdapter());
Hive.registerAdapter(RcmdStatAdapter());
Hive.registerAdapter(RcmdOwnerAdapter());
Hive.registerAdapter(OwnerAdapter()); Hive.registerAdapter(OwnerAdapter());
Hive.registerAdapter(UserInfoDataAdapter()); Hive.registerAdapter(UserInfoDataAdapter());
Hive.registerAdapter(LevelInfoAdapter()); Hive.registerAdapter(LevelInfoAdapter());
@@ -73,8 +60,6 @@ class GStrorage {
static Future<void> close() async { static Future<void> close() async {
// user.compact(); // user.compact();
// user.close(); // user.close();
recVideo.compact();
recVideo.close();
userInfo.compact(); userInfo.compact();
userInfo.close(); userInfo.close();
historyword.compact(); historyword.compact();