mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-17 16:00:13 +08:00
Compare commits
11 Commits
1.1.5-pre2
...
1.1.5-pre4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
861365930d | ||
|
|
0d4d92a202 | ||
|
|
4c6ad0e385 | ||
|
|
ad45e995e2 | ||
|
|
50a035a479 | ||
|
|
c0dbd6cbb2 | ||
|
|
686af4a330 | ||
|
|
46aad06e34 | ||
|
|
3921b2304d | ||
|
|
bca5b0419c | ||
|
|
9754b061dd |
@@ -7,6 +7,7 @@ Future<void> showConfirmDialog({
|
||||
dynamic content,
|
||||
required VoidCallback onConfirm,
|
||||
}) {
|
||||
assert(content is String? || content is Widget);
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
|
||||
@@ -972,4 +972,6 @@ class Api {
|
||||
static const String followedUp = '/x/relation/followings/followed_upper';
|
||||
|
||||
static const String sameFollowing = '/x/relation/same/followings';
|
||||
|
||||
static const String seasonStatus = '/pgc/view/web/season/user/status';
|
||||
}
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
import 'package:PiliPlus/http/api.dart';
|
||||
import 'package:PiliPlus/http/init.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/user/danmaku_block.dart';
|
||||
import 'package:PiliPlus/utils/accounts.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
class DanmakuFilterHttp {
|
||||
static Future danmakuFilter() async {
|
||||
static Future<LoadingState<DanmakuBlockDataModel>> danmakuFilter() async {
|
||||
var res = await Request().get(Api.danmakuFilter);
|
||||
if (res.data['code'] == 0) {
|
||||
return {
|
||||
'status': true,
|
||||
'data': DanmakuBlockDataModel.fromJson(res.data['data']),
|
||||
};
|
||||
return Success(DanmakuBlockDataModel.fromJson(res.data['data']));
|
||||
} else {
|
||||
return {
|
||||
'status': false,
|
||||
'msg': res.data['message'],
|
||||
};
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
}
|
||||
|
||||
static Future danmakuFilterDel({required int ids}) async {
|
||||
static Future<LoadingState<Null>> danmakuFilterDel({required int ids}) async {
|
||||
var res = await Request().post(
|
||||
Api.danmakuFilterDel,
|
||||
data: {
|
||||
@@ -30,16 +25,13 @@ class DanmakuFilterHttp {
|
||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return {'status': true};
|
||||
return const Success(null);
|
||||
} else {
|
||||
return {
|
||||
'status': false,
|
||||
'msg': res.data['message'],
|
||||
};
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
}
|
||||
|
||||
static Future danmakuFilterAdd({
|
||||
static Future<LoadingState<SimpleRule>> danmakuFilterAdd({
|
||||
required String filter,
|
||||
required int type,
|
||||
}) async {
|
||||
@@ -53,15 +45,9 @@ class DanmakuFilterHttp {
|
||||
options: Options(contentType: Headers.formUrlEncodedContentType),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return {
|
||||
'status': true,
|
||||
'data': SimpleRule.fromJson(res.data['data']),
|
||||
};
|
||||
return Success(SimpleRule.fromJson(res.data['data']));
|
||||
} else {
|
||||
return {
|
||||
'status': false,
|
||||
'msg': res.data['message'],
|
||||
};
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,4 +242,18 @@ class PgcHttp {
|
||||
return {'status': false, 'msg': res.data['message']};
|
||||
}
|
||||
}
|
||||
|
||||
static Future seasonStatus(dynamic seasonId) async {
|
||||
var res = await Request().get(
|
||||
Api.seasonStatus,
|
||||
queryParameters: {
|
||||
'season_id': seasonId,
|
||||
},
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
return {'status': true, 'data': res.data['result']};
|
||||
} else {
|
||||
return {'status': false, 'msg': res.data['message']};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ enum UaType {
|
||||
),
|
||||
pc(
|
||||
'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;
|
||||
|
||||
|
||||
@@ -1068,11 +1068,10 @@ class VideoHttp {
|
||||
required int playurlType, // ugc 1, pgc 2
|
||||
int? qn,
|
||||
}) async {
|
||||
final accessKey = Accounts.accountMode[AccountType.video.index].accessKey;
|
||||
final accessKey = Accounts.get(AccountType.video).accessKey;
|
||||
final params = {
|
||||
'access_key': ?accessKey,
|
||||
'actionKey': 'appkey',
|
||||
'appkey': Constants.appKey,
|
||||
'cid': cid,
|
||||
'fourk': 1,
|
||||
'is_proj': 1,
|
||||
|
||||
@@ -2,7 +2,8 @@ enum AccountType {
|
||||
main('主账号'),
|
||||
heartbeat('记录观看'),
|
||||
recommend('推荐'),
|
||||
video('视频取流');
|
||||
video('视频取流')
|
||||
;
|
||||
|
||||
final String title;
|
||||
const AccountType(this.title);
|
||||
|
||||
@@ -3,7 +3,8 @@ enum AudioNormalization {
|
||||
// ref https://github.com/KRTirtho/spotube/commit/da10ab2e291d4ba4d3082b9a6ae535639fb8f1b7
|
||||
dynaudnorm('预设 dynaudnorm', 'dynaudnorm=g=5:f=250:r=0.9:p=0.5'),
|
||||
loudnorm('预设 loudnorm', 'loudnorm=I=-16:LRA=11:TP=-1.5'),
|
||||
custom('自定义参数');
|
||||
custom('自定义参数')
|
||||
;
|
||||
|
||||
final String title;
|
||||
final String param;
|
||||
|
||||
@@ -4,7 +4,8 @@ enum BadgeType {
|
||||
none(),
|
||||
vip('大会员'),
|
||||
person('认证个人', Color(0xFFFFCC00)),
|
||||
institution('认证机构', Colors.lightBlueAccent);
|
||||
institution('认证机构', Colors.lightBlueAccent)
|
||||
;
|
||||
|
||||
final String? desc;
|
||||
final Color? color;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
enum DmBlockType {
|
||||
keyword('关键词'),
|
||||
regex('正则'),
|
||||
uid('用户');
|
||||
uid('用户')
|
||||
;
|
||||
|
||||
final String label;
|
||||
const DmBlockType(this.label);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
enum DynamicBadgeMode {
|
||||
hidden('隐藏'),
|
||||
point('红点'),
|
||||
number('数字');
|
||||
number('数字')
|
||||
;
|
||||
|
||||
final String desc;
|
||||
const DynamicBadgeMode(this.desc);
|
||||
|
||||
@@ -3,7 +3,8 @@ enum DynamicsTabType {
|
||||
video('投稿'),
|
||||
pgc('番剧'),
|
||||
article('专栏'),
|
||||
up('UP');
|
||||
up('UP')
|
||||
;
|
||||
|
||||
final String label;
|
||||
const DynamicsTabType(this.label);
|
||||
|
||||
@@ -3,7 +3,8 @@ enum UpPanelPosition {
|
||||
leftFixed('左侧常驻'),
|
||||
rightFixed('右侧常驻'),
|
||||
leftDrawer('左侧抽屉'),
|
||||
rightDrawer('右侧抽屉');
|
||||
rightDrawer('右侧抽屉')
|
||||
;
|
||||
|
||||
final String label;
|
||||
const UpPanelPosition(this.label);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
enum EpisodeType {
|
||||
part('分P'),
|
||||
season('合集'),
|
||||
pgc('剧集');
|
||||
pgc('剧集')
|
||||
;
|
||||
|
||||
final String title;
|
||||
const EpisodeType(this.title);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
enum FavOrderType {
|
||||
mtime('最近收藏'),
|
||||
view('最多播放'),
|
||||
pubtime('最近投稿');
|
||||
pubtime('最近投稿')
|
||||
;
|
||||
|
||||
final String label;
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@ enum FavTabType {
|
||||
article('专栏', FavArticlePage()),
|
||||
note('笔记', FavNotePage()),
|
||||
topic('话题', FavTopicPage()),
|
||||
cheese('课堂', FavCheesePage());
|
||||
cheese('课堂', FavCheesePage())
|
||||
;
|
||||
|
||||
final String title;
|
||||
final Widget page;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
enum FollowOrderType {
|
||||
def('', '最近关注'),
|
||||
attention('attention', '最常访问');
|
||||
attention('attention', '最常访问')
|
||||
;
|
||||
|
||||
final String type;
|
||||
final String title;
|
||||
|
||||
@@ -19,7 +19,8 @@ enum HomeTabType implements EnumWithLabel {
|
||||
hot('热门'),
|
||||
rank('分区'),
|
||||
bangumi('番剧'),
|
||||
cinema('影视');
|
||||
cinema('影视')
|
||||
;
|
||||
|
||||
@override
|
||||
final String label;
|
||||
|
||||
@@ -8,7 +8,8 @@ enum MemberTabType {
|
||||
favorite('收藏'),
|
||||
bangumi('番剧'),
|
||||
cheese('课堂'),
|
||||
shop('小店');
|
||||
shop('小店')
|
||||
;
|
||||
|
||||
static bool showMemberShop = Pref.showMemberShop;
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ enum MsgUnReadType {
|
||||
reply('回复我的'),
|
||||
at('@我'),
|
||||
like('收到的赞'),
|
||||
sysMsg('系统通知');
|
||||
sysMsg('系统通知')
|
||||
;
|
||||
|
||||
final String title;
|
||||
const MsgUnReadType(this.title);
|
||||
|
||||
@@ -22,7 +22,8 @@ enum NavigationBarType implements EnumWithLabel {
|
||||
Icon(Icons.person_outline, size: 21),
|
||||
Icon(Icons.person, size: 21),
|
||||
MinePage(),
|
||||
);
|
||||
)
|
||||
;
|
||||
|
||||
@override
|
||||
final String label;
|
||||
|
||||
@@ -2,7 +2,8 @@ import 'package:PiliPlus/http/api.dart';
|
||||
|
||||
enum PgcReviewType {
|
||||
long(label: '长评', api: Api.pgcReviewL),
|
||||
short(label: '短评', api: Api.pgcReviewS);
|
||||
short(label: '短评', api: Api.pgcReviewS)
|
||||
;
|
||||
|
||||
final String label;
|
||||
final String api;
|
||||
@@ -14,7 +15,8 @@ enum PgcReviewType {
|
||||
|
||||
enum PgcReviewSortType {
|
||||
def('默认', 0),
|
||||
latest('最新', 1);
|
||||
latest('最新', 1)
|
||||
;
|
||||
|
||||
final int sort;
|
||||
final String label;
|
||||
|
||||
@@ -19,7 +19,8 @@ enum RankType {
|
||||
documentary('记录', seasonType: 3),
|
||||
movie('电影', seasonType: 2),
|
||||
tv('剧集', seasonType: 5),
|
||||
variety('综艺', seasonType: 7);
|
||||
variety('综艺', seasonType: 7)
|
||||
;
|
||||
|
||||
final String label;
|
||||
final int? rid;
|
||||
|
||||
@@ -4,7 +4,8 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart
|
||||
enum ReplyOptionType {
|
||||
allow('允许评论'),
|
||||
close('关闭评论'),
|
||||
choose('精选评论');
|
||||
choose('精选评论')
|
||||
;
|
||||
|
||||
final String title;
|
||||
const ReplyOptionType(this.title);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
enum ReplySortType {
|
||||
time('最新评论', '最新'),
|
||||
hot('最热评论', '最热');
|
||||
hot('最热评论', '最热')
|
||||
;
|
||||
|
||||
final String title;
|
||||
final String label;
|
||||
|
||||
@@ -3,7 +3,8 @@ enum ArticleOrderType {
|
||||
pubdate('最新发布'),
|
||||
click('最多点击'),
|
||||
attention('最多喜欢'),
|
||||
scores('最多评论');
|
||||
scores('最多评论')
|
||||
;
|
||||
|
||||
String get order => name;
|
||||
final String label;
|
||||
@@ -19,7 +20,8 @@ enum ArticleZoneType {
|
||||
interest('兴趣', 29),
|
||||
novel('轻小说', 16),
|
||||
tech('科技', 17),
|
||||
note('笔记', 41);
|
||||
note('笔记', 41)
|
||||
;
|
||||
|
||||
final String label;
|
||||
final int categoryId;
|
||||
|
||||
@@ -18,7 +18,8 @@ enum SearchType {
|
||||
// 用户:bili_user
|
||||
bili_user('用户'),
|
||||
// 专栏:article
|
||||
article('专栏');
|
||||
article('专栏')
|
||||
;
|
||||
// 相簿:photo
|
||||
// photo
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ enum UserOrderType {
|
||||
fansDesc('粉丝数由高到低', 0, 'fans'),
|
||||
fansAsc('粉丝数由低到高', 1, 'fans'),
|
||||
levelDesc('Lv等级由高到低', 0, 'level'),
|
||||
levelAsc('Lv等级由低到高', 1, 'level');
|
||||
levelAsc('Lv等级由低到高', 1, 'level')
|
||||
;
|
||||
|
||||
final String label;
|
||||
final int orderSort;
|
||||
@@ -15,7 +16,8 @@ enum UserType {
|
||||
all('全部用户'),
|
||||
up('UP主'),
|
||||
common('普通用户'),
|
||||
verified('认证用户');
|
||||
verified('认证用户')
|
||||
;
|
||||
|
||||
final String label;
|
||||
const UserType(this.label);
|
||||
|
||||
@@ -2,7 +2,8 @@ enum VideoPubTimeType {
|
||||
all('不限'),
|
||||
day('最近一天'),
|
||||
week('最近一周'),
|
||||
halfYear('最近半年');
|
||||
halfYear('最近半年')
|
||||
;
|
||||
|
||||
final String label;
|
||||
const VideoPubTimeType(this.label);
|
||||
@@ -13,7 +14,8 @@ enum VideoDurationType {
|
||||
tenMins('0-10分钟'),
|
||||
halfHour('10-30分钟'),
|
||||
hour('30-60分钟'),
|
||||
hourPlus('60分钟+');
|
||||
hourPlus('60分钟+')
|
||||
;
|
||||
|
||||
final String label;
|
||||
const VideoDurationType(this.label);
|
||||
@@ -41,7 +43,8 @@ enum VideoZoneType {
|
||||
cinephile('影视', tids: 181),
|
||||
documentary('记录', tids: 177),
|
||||
movie('电影', tids: 23),
|
||||
tv('电视', tids: 11);
|
||||
tv('电视', tids: 11)
|
||||
;
|
||||
|
||||
final String label;
|
||||
final int? tids;
|
||||
@@ -55,7 +58,8 @@ enum ArchiveFilterType {
|
||||
pubdate('新发布'),
|
||||
dm('弹幕多'),
|
||||
stow('收藏多'),
|
||||
scores('评论多');
|
||||
scores('评论多')
|
||||
;
|
||||
// 专栏
|
||||
// attention('最多喜欢'),
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ enum SettingType {
|
||||
styleSetting('外观设置'),
|
||||
extraSetting('其它设置'),
|
||||
webdavSetting('WebDAV 设置'),
|
||||
about('关于');
|
||||
about('关于')
|
||||
;
|
||||
|
||||
final String title;
|
||||
const SettingType(this.title);
|
||||
|
||||
@@ -2,7 +2,8 @@ enum ActionType {
|
||||
skip('跳过'),
|
||||
mute('静音'),
|
||||
full('整个视频'),
|
||||
poi('精彩时刻');
|
||||
poi('精彩时刻')
|
||||
;
|
||||
|
||||
final String title;
|
||||
const ActionType(this.title);
|
||||
|
||||
@@ -97,7 +97,8 @@ enum SegmentType {
|
||||
'仅用于对整个视频进行标记。适用于展示UP主免费或获得补贴后使用的产品、服务或场地的视频。',
|
||||
Color(0xFF008a5c),
|
||||
[ActionType.full],
|
||||
);
|
||||
)
|
||||
;
|
||||
|
||||
/// from https://github.com/hanydd/BilibiliSponsorBlock/blob/master/public/_locales/zh_CN/messages.json
|
||||
final String title;
|
||||
|
||||
@@ -3,7 +3,8 @@ enum SkipType {
|
||||
skipOnce('跳过一次'),
|
||||
skipManually('手动跳过'),
|
||||
showOnly('仅显示'),
|
||||
disable('禁用');
|
||||
disable('禁用')
|
||||
;
|
||||
|
||||
final String title;
|
||||
const SkipType(this.title);
|
||||
|
||||
@@ -7,7 +7,8 @@ enum StatType {
|
||||
reply(Icons.comment_outlined, '评论'),
|
||||
follow(Icons.favorite_border, '关注'),
|
||||
play(Icons.play_circle_outlined, '播放'),
|
||||
listen(Icons.headset_outlined, '播放');
|
||||
listen(Icons.headset_outlined, '播放')
|
||||
;
|
||||
|
||||
final IconData iconData;
|
||||
final String label;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
enum SuperResolutionType {
|
||||
disable('禁用'),
|
||||
efficiency('效率'),
|
||||
quality('画质');
|
||||
quality('画质')
|
||||
;
|
||||
|
||||
final String title;
|
||||
const SuperResolutionType(this.title);
|
||||
|
||||
@@ -4,7 +4,8 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart
|
||||
enum ThemeType {
|
||||
light('浅色'),
|
||||
dark('深色'),
|
||||
system('跟随系统');
|
||||
system('跟随系统')
|
||||
;
|
||||
|
||||
final String desc;
|
||||
const ThemeType(this.desc);
|
||||
|
||||
@@ -6,7 +6,8 @@ enum AudioQuality {
|
||||
dolby(30250, '杜比全景声'),
|
||||
k192(30280, '192K'),
|
||||
k132(30232, '132K'),
|
||||
k64(30216, '64K');
|
||||
k64(30216, '64K')
|
||||
;
|
||||
|
||||
final int code;
|
||||
final String desc;
|
||||
|
||||
@@ -24,7 +24,8 @@ enum CDNService {
|
||||
aliov('aliov(阿里云海外)', 'upos-sz-mirroraliov.bilivideo.com'),
|
||||
cosov('cosov(腾讯云海外)', 'upos-sz-mirrorcosov.bilivideo.com'),
|
||||
hwov('hwov(华为云海外)', 'upos-sz-mirrorhwov.bilivideo.com'),
|
||||
hk_bcache('hk_bcache(Bilibili海外)', 'cn-hk-eq-bcache-01.bilivideo.com');
|
||||
hk_bcache('hk_bcache(Bilibili海外)', 'cn-hk-eq-bcache-01.bilivideo.com')
|
||||
;
|
||||
|
||||
String get code => name;
|
||||
static final fromCode = values.byName;
|
||||
|
||||
@@ -6,7 +6,8 @@ enum LiveQuality {
|
||||
bluRay(400, '蓝光'),
|
||||
superHD(250, '超清'),
|
||||
smooth(150, '高清'),
|
||||
flunt(80, '流畅');
|
||||
flunt(80, '流畅')
|
||||
;
|
||||
|
||||
final int code;
|
||||
final String desc;
|
||||
|
||||
@@ -26,7 +26,8 @@ enum SourceType {
|
||||
extraId: 4,
|
||||
playlistSource: PlaylistSource.MEDIA_LIST,
|
||||
),
|
||||
file;
|
||||
file
|
||||
;
|
||||
|
||||
final int? mediaType;
|
||||
final int? extraId;
|
||||
|
||||
@@ -2,7 +2,8 @@ enum SubtitlePrefType {
|
||||
off('默认不显示字幕'),
|
||||
on('优先选择非自动生成(ai)字幕'),
|
||||
withoutAi('跳过自动生成(ai)字幕,选择第一个可用字幕'),
|
||||
auto('静音时等同第二项,非静音时等同第三项');
|
||||
auto('静音时等同第二项,非静音时等同第三项')
|
||||
;
|
||||
|
||||
final String desc;
|
||||
const SubtitlePrefType(this.desc);
|
||||
|
||||
@@ -4,7 +4,8 @@ enum VideoDecodeFormatType {
|
||||
DVH1(['dvh1']),
|
||||
AV1(['av01']),
|
||||
HEVC(['hev1', 'hvc1']),
|
||||
AVC(['avc1']);
|
||||
AVC(['avc1'])
|
||||
;
|
||||
|
||||
String get description => name;
|
||||
final List<String> codes;
|
||||
|
||||
@@ -11,7 +11,8 @@ enum VideoQuality {
|
||||
high720(64, '720P 准高清', '720P'),
|
||||
clear480(32, '480P 标清', '480P'),
|
||||
fluent360(16, '360P 流畅', '360P'),
|
||||
speed240(6, '240P 极速', '240P');
|
||||
speed240(6, '240P 极速', '240P')
|
||||
;
|
||||
|
||||
final int code;
|
||||
final String desc;
|
||||
|
||||
@@ -13,7 +13,8 @@ enum VideoType {
|
||||
type: 10,
|
||||
replyType: 33,
|
||||
api: Api.pugvUrl,
|
||||
);
|
||||
)
|
||||
;
|
||||
|
||||
final int type;
|
||||
final String api;
|
||||
|
||||
@@ -4,7 +4,8 @@ enum WebviewMenuItem {
|
||||
openInBrowser('浏览器中打开'),
|
||||
clearCache('清除缓存'),
|
||||
resetCookie('重新设置Cookie'),
|
||||
goBack('返回');
|
||||
goBack('返回')
|
||||
;
|
||||
|
||||
final String title;
|
||||
const WebviewMenuItem(this.title);
|
||||
|
||||
@@ -201,7 +201,10 @@ class Durl {
|
||||
final _ipRegExp = RegExp(r'^https?://\d{1,3}\.\d{1,3}');
|
||||
|
||||
bool _isMCDNorPCDN(String url) {
|
||||
return url.contains("szbdyd.com") ||
|
||||
return url.contains("upos-sz-302") ||
|
||||
url.contains("nexusedgeio.com") ||
|
||||
url.contains("ahdohpiechei.com") ||
|
||||
url.contains("szbdyd.com") ||
|
||||
url.contains(".mcdn.bilivideo") ||
|
||||
_ipRegExp.hasMatch(url);
|
||||
}
|
||||
@@ -339,6 +342,7 @@ class Volume {
|
||||
final num targetOffset;
|
||||
final num targetI;
|
||||
final num targetTp;
|
||||
|
||||
// final MultiSceneArgs? multiSceneArgs;
|
||||
|
||||
factory Volume.fromJson(Map<String, dynamic> json) {
|
||||
|
||||
@@ -465,7 +465,8 @@ enum DownloadStatus {
|
||||
failDanmaku('获取弹幕失败'),
|
||||
failPlayUrl('获取播放地址失败'),
|
||||
pause('暂停中'),
|
||||
wait('等待中');
|
||||
wait('等待中')
|
||||
;
|
||||
|
||||
final String message;
|
||||
const DownloadStatus(this.message);
|
||||
|
||||
@@ -32,10 +32,10 @@ class DanmakuBlockController extends GetxController
|
||||
|
||||
Future<void> queryDanmakuFilter() async {
|
||||
SmartDialog.showLoading(msg: '正在同步弹幕屏蔽规则……');
|
||||
var result = await DanmakuFilterHttp.danmakuFilter();
|
||||
final result = await DanmakuFilterHttp.danmakuFilter();
|
||||
SmartDialog.dismiss();
|
||||
if (result['status']) {
|
||||
DanmakuBlockDataModel data = result['data'];
|
||||
if (result.isSuccess) {
|
||||
final data = result.data;
|
||||
rules[0].addAll(data.rule);
|
||||
rules[1].addAll(data.rule1);
|
||||
rules[2].addAll(data.rule2);
|
||||
@@ -43,19 +43,19 @@ class DanmakuBlockController extends GetxController
|
||||
SmartDialog.showToast(data.toast!);
|
||||
}
|
||||
} else {
|
||||
SmartDialog.showToast(result['msg']);
|
||||
result.toast();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> danmakuFilterDel(int tabIndex, int itemIndex, int id) async {
|
||||
SmartDialog.showLoading(msg: '正在删除弹幕屏蔽规则……');
|
||||
var result = await DanmakuFilterHttp.danmakuFilterDel(ids: id);
|
||||
final result = await DanmakuFilterHttp.danmakuFilterDel(ids: id);
|
||||
SmartDialog.dismiss();
|
||||
if (result['status']) {
|
||||
if (result.isSuccess) {
|
||||
rules[tabIndex].removeAt(itemIndex);
|
||||
SmartDialog.showToast('删除成功');
|
||||
} else {
|
||||
SmartDialog.showToast(result['msg']);
|
||||
result.toast();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,17 +67,16 @@ class DanmakuBlockController extends GetxController
|
||||
filter = Crc32Xz().convert(utf8.encode(filter)).toRadixString(16);
|
||||
}
|
||||
SmartDialog.showLoading(msg: '正在添加弹幕屏蔽规则……');
|
||||
var result = await DanmakuFilterHttp.danmakuFilterAdd(
|
||||
final result = await DanmakuFilterHttp.danmakuFilterAdd(
|
||||
filter: filter,
|
||||
type: type,
|
||||
);
|
||||
SmartDialog.dismiss();
|
||||
if (result['status']) {
|
||||
SimpleRule rule = result['data'];
|
||||
rules[type].add(rule);
|
||||
if (result.isSuccess) {
|
||||
rules[type].add(result.data);
|
||||
SmartDialog.showToast('添加成功');
|
||||
} else {
|
||||
SmartDialog.showToast(result['msg']);
|
||||
result.toast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
|
||||
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
||||
import 'package:PiliPlus/common/widgets/keep_alive_wrapper.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
|
||||
@@ -71,6 +72,7 @@ class _DanmakuBlockPageState extends State<DanmakuBlockPage> {
|
||||
.toList(),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
tooltip: '添加',
|
||||
onPressed: () =>
|
||||
_showAddDialog(DmBlockType.values[_controller.tabController.index]),
|
||||
child: const Icon(Icons.add),
|
||||
@@ -78,7 +80,7 @@ class _DanmakuBlockPageState extends State<DanmakuBlockPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget tabViewBuilder(int tabIndex, List<SimpleRule> list) {
|
||||
Widget tabViewBuilder(final int tabIndex, List<SimpleRule> list) {
|
||||
if (list.isEmpty) {
|
||||
return scrollErrorWidget();
|
||||
}
|
||||
@@ -89,31 +91,58 @@ class _DanmakuBlockPageState extends State<DanmakuBlockPage> {
|
||||
),
|
||||
itemBuilder: (context, itemIndex) {
|
||||
final SimpleRule item = list[itemIndex];
|
||||
final child = iconButton(
|
||||
iconSize: 20,
|
||||
tooltip: '删除',
|
||||
icon: const Icon(Icons.delete_outlined),
|
||||
onPressed: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定删除该规则?',
|
||||
onConfirm: () => _controller.danmakuFilterDel(
|
||||
tabIndex,
|
||||
itemIndex,
|
||||
item.id,
|
||||
),
|
||||
),
|
||||
);
|
||||
return ListTile(
|
||||
title: Text(
|
||||
item.filter,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.delete_outlined),
|
||||
onPressed: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定删除该规则?',
|
||||
onConfirm: () => _controller.danmakuFilterDel(
|
||||
tabIndex,
|
||||
itemIndex,
|
||||
item.id,
|
||||
),
|
||||
),
|
||||
),
|
||||
trailing: tabIndex == 2
|
||||
? child
|
||||
: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
iconButton(
|
||||
iconSize: 20,
|
||||
tooltip: '编辑',
|
||||
icon: const Icon(Icons.edit_outlined),
|
||||
onPressed: () => _showAddDialog(
|
||||
DmBlockType.values[_controller.tabController.index],
|
||||
initFilter: item.filter,
|
||||
itemIndex: itemIndex,
|
||||
itemId: item.id,
|
||||
),
|
||||
),
|
||||
child,
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _showAddDialog(DmBlockType type) {
|
||||
String filter = '';
|
||||
String hintText = switch (type) {
|
||||
void _showAddDialog(
|
||||
DmBlockType type, {
|
||||
String initFilter = '',
|
||||
int? itemIndex,
|
||||
int? itemId,
|
||||
}) {
|
||||
assert((itemIndex == null) == (itemId == null));
|
||||
String filter = initFilter;
|
||||
final hintText = switch (type) {
|
||||
DmBlockType.keyword => '输入过滤的关键词,其它类别请切换标签页后添加',
|
||||
DmBlockType.regex => '输入//之间的正则表达式,无需包含头尾的"/"',
|
||||
DmBlockType.uid => '输入用户UID',
|
||||
@@ -123,7 +152,7 @@ class _DanmakuBlockPageState extends State<DanmakuBlockPage> {
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text('添加新的${type.label}规则'),
|
||||
title: Text('${itemId != null ? "编辑" : "添加新的"}${type.label}规则'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -149,16 +178,25 @@ class _DanmakuBlockPageState extends State<DanmakuBlockPage> {
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('添加'),
|
||||
onPressed: () {
|
||||
if (filter.isNotEmpty) {
|
||||
child: const Text('确定'),
|
||||
onPressed: () async {
|
||||
if (filter != initFilter) {
|
||||
Get.back();
|
||||
_controller.danmakuFilterAdd(
|
||||
if (itemId != null) {
|
||||
await _controller.danmakuFilterDel(
|
||||
type.index,
|
||||
itemIndex!,
|
||||
itemId,
|
||||
);
|
||||
}
|
||||
await _controller.danmakuFilterAdd(
|
||||
filter: filter,
|
||||
type: type.index,
|
||||
);
|
||||
} else {
|
||||
SmartDialog.showToast('输入内容不能为空');
|
||||
SmartDialog.showToast(
|
||||
'输入内容${filter.isEmpty ? "不能为空" : "与上次相同"}',
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
@@ -76,6 +76,8 @@ class DetailItem extends StatelessWidget {
|
||||
);
|
||||
if (res) {
|
||||
SmartDialog.showToast('更新成功');
|
||||
} else {
|
||||
SmartDialog.showToast('更新失败');
|
||||
}
|
||||
},
|
||||
dense: true,
|
||||
|
||||
@@ -78,7 +78,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
if (kDebugMode || Utils.isMobile)
|
||||
TextButton.icon(
|
||||
onPressed: () => PageUtils.launchURL(
|
||||
_loginPageCtr.codeInfo.value.data.url,
|
||||
'bilibili://browser?url=${Uri.encodeComponent(_loginPageCtr.codeInfo.value.data.url)}',
|
||||
mode: LaunchMode.externalNonBrowserApplication,
|
||||
),
|
||||
icon: const Icon(Icons.open_in_browser_outlined),
|
||||
|
||||
@@ -356,7 +356,6 @@ class _MediaPageState extends CommonPageState<MinePage, MineController>
|
||||
value: hasLevel
|
||||
? levelInfo.currentExp! / levelInfo.nextExp!
|
||||
: 0,
|
||||
trackGap: hasLevel ? null : 0,
|
||||
backgroundColor: theme.colorScheme.outline.withValues(
|
||||
alpha: 0.4,
|
||||
),
|
||||
|
||||
@@ -3,9 +3,12 @@ import 'dart:math';
|
||||
import 'package:PiliPlus/common/widgets/pair.dart';
|
||||
import 'package:PiliPlus/http/constants.dart';
|
||||
import 'package:PiliPlus/http/init.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/common/sponsor_block/segment_type.dart';
|
||||
import 'package:PiliPlus/models/common/sponsor_block/skip_type.dart';
|
||||
import 'package:PiliPlus/pages/setting/slide_color_picker.dart';
|
||||
import 'package:PiliPlus/utils/duration_utils.dart';
|
||||
import 'package:PiliPlus/utils/num_utils.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage.dart';
|
||||
import 'package:PiliPlus/utils/storage_key.dart';
|
||||
@@ -35,7 +38,8 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
bool _blockToast = Pref.blockToast;
|
||||
String _blockServer = Pref.blockServer;
|
||||
bool _blockTrack = Pref.blockTrack;
|
||||
final Rx<bool?> _serverStatus = Rx<bool?>(null);
|
||||
final _serverStatus = Rxn<bool>();
|
||||
final _userInfo = LoadingState<_UserInfo>.loading().obs;
|
||||
|
||||
Box setting = GStorage.setting;
|
||||
|
||||
@@ -43,6 +47,7 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_checkServerStatus();
|
||||
_getUserInfo();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -60,6 +65,22 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _getUserInfo() async {
|
||||
final params = {
|
||||
'userID': _userId,
|
||||
'values': '["viewCount","minutesSaved","segmentCount"]',
|
||||
};
|
||||
final res = await Request().get(
|
||||
'$_blockServer/api/userInfo',
|
||||
queryParameters: params,
|
||||
);
|
||||
if (res.statusCode == 200) {
|
||||
_userInfo.value = Success(_UserInfo.fromJson(res.data));
|
||||
} else {
|
||||
_userInfo.value = Error(res.data['message']);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _blockLimitItem(
|
||||
ThemeData theme,
|
||||
TextStyle titleStyle,
|
||||
@@ -270,6 +291,37 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
},
|
||||
);
|
||||
|
||||
Widget _blockUserInfo(
|
||||
ThemeData theme,
|
||||
TextStyle titleStyle,
|
||||
TextStyle subTitleStyle,
|
||||
) => Obx(
|
||||
() {
|
||||
return ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
_userInfo.value = LoadingState.loading();
|
||||
_getUserInfo();
|
||||
},
|
||||
title: Text(
|
||||
'您的信息',
|
||||
style: titleStyle,
|
||||
),
|
||||
subtitle: switch (_userInfo.value) {
|
||||
Loading() => const SizedBox.shrink(),
|
||||
Success<_UserInfo>(:final response) => Text(
|
||||
response.toString(),
|
||||
style: subTitleStyle,
|
||||
),
|
||||
Error(:final errMsg) => Text(
|
||||
errMsg ?? '服务器错误',
|
||||
style: subTitleStyle.copyWith(color: theme.colorScheme.error),
|
||||
),
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Widget _blockServerItem(
|
||||
ThemeData theme,
|
||||
TextStyle titleStyle,
|
||||
@@ -316,6 +368,8 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
_blockServer = _textController.text;
|
||||
setting.put(SettingBoxKey.blockServer, _blockServer);
|
||||
Request.accountManager.blockServer = _blockServer;
|
||||
_checkServerStatus();
|
||||
_getUserInfo();
|
||||
(context as Element).markNeedsBuild();
|
||||
},
|
||||
child: const Text('确定'),
|
||||
@@ -461,6 +515,10 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
SliverToBoxAdapter(child: _blockToastItem(titleStyle)),
|
||||
sliverDivider,
|
||||
SliverToBoxAdapter(child: _blockTrackItem(titleStyle, subTitleStyle)),
|
||||
sliverDivider,
|
||||
SliverToBoxAdapter(
|
||||
child: _blockUserInfo(theme, titleStyle, subTitleStyle),
|
||||
),
|
||||
dividerL,
|
||||
SliverList.separated(
|
||||
itemCount: _blockSettings.length,
|
||||
@@ -599,3 +657,34 @@ class _SponsorBlockPageState extends State<SponsorBlockPage> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _UserInfo {
|
||||
final int viewCount;
|
||||
final double minutesSaved;
|
||||
final int segmentCount;
|
||||
|
||||
const _UserInfo({
|
||||
required this.viewCount,
|
||||
required this.minutesSaved,
|
||||
required this.segmentCount,
|
||||
});
|
||||
|
||||
factory _UserInfo.fromJson(Map<String, dynamic> json) => _UserInfo(
|
||||
viewCount: json['viewCount'],
|
||||
minutesSaved: (json['minutesSaved'] as num).toDouble(),
|
||||
segmentCount: json['segmentCount'],
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
String minutes = DurationUtils.formatTimeDuration(
|
||||
Duration(minutes: minutesSaved.round()),
|
||||
);
|
||||
if (minutes.isEmpty) {
|
||||
minutes = '0分钟';
|
||||
}
|
||||
return ('您提交了 ${NumUtils.formatPositiveDecimal(segmentCount)} 片段\n'
|
||||
'您为大家节省了 ${NumUtils.formatPositiveDecimal(viewCount)} 片段\n'
|
||||
'($minutes 的生命)');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1126,7 +1126,7 @@ class VideoDetailController extends GetxController
|
||||
currentDecodeFormats = VideoDecodeFormatType.fromString(video.codecs!);
|
||||
}
|
||||
firstVideo = video;
|
||||
videoUrl = video.baseUrl!;
|
||||
videoUrl = VideoUtils.getCdnUrl(firstVideo);
|
||||
|
||||
/// 根据currentAudioQa 重新设置audioUrl
|
||||
if (currentAudioQa != null) {
|
||||
@@ -1134,7 +1134,7 @@ class VideoDetailController extends GetxController
|
||||
(i) => i.id == currentAudioQa!.code,
|
||||
orElse: () => data.dash!.audio!.first,
|
||||
);
|
||||
audioUrl = firstAudio.baseUrl ?? '';
|
||||
audioUrl = VideoUtils.getCdnUrl(firstAudio);
|
||||
}
|
||||
|
||||
playerInit();
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math' show max;
|
||||
|
||||
import 'package:PiliPlus/grpc/bilibili/app/viewunite/pgcanymodel.pb.dart'
|
||||
show ViewPgcAny;
|
||||
import 'package:PiliPlus/grpc/view.dart';
|
||||
import 'package:PiliPlus/http/constants.dart';
|
||||
import 'package:PiliPlus/http/fav.dart';
|
||||
import 'package:PiliPlus/http/pgc.dart';
|
||||
import 'package:PiliPlus/http/search.dart';
|
||||
import 'package:PiliPlus/http/video.dart';
|
||||
import 'package:PiliPlus/models/common/video/source_type.dart';
|
||||
@@ -448,7 +446,7 @@ class PgcIntroController extends CommonIntroController {
|
||||
}
|
||||
}
|
||||
|
||||
void queryIsFollowed() {
|
||||
Future<void> queryIsFollowed() async {
|
||||
// try {
|
||||
// var result = await Request().get(
|
||||
// 'https://www.bilibili.com/bangumi/play/ss$seasonId',
|
||||
@@ -464,14 +462,22 @@ class PgcIntroController extends CommonIntroController {
|
||||
// scriptContent['props']['pageProps']['followState']['followStatus'];
|
||||
// }
|
||||
// } catch (_) {}
|
||||
ViewGrpc.view(bvid: bvid).then((res) {
|
||||
if (res.isSuccess) {
|
||||
ViewPgcAny view = ViewPgcAny.fromBuffer(res.data.supplement.value);
|
||||
var userStatus = view.ogvData.userStatus;
|
||||
isFollowed.value = userStatus.follow == 1;
|
||||
followStatus.value = userStatus.followStatus;
|
||||
}
|
||||
});
|
||||
|
||||
// ViewGrpc.view(bvid: bvid).then((res) {
|
||||
// if (res.isSuccess) {
|
||||
// ViewPgcAny view = ViewPgcAny.fromBuffer(res.data.supplement.value);
|
||||
// var userStatus = view.ogvData.userStatus;
|
||||
// isFollowed.value = userStatus.follow == 1;
|
||||
// followStatus.value = userStatus.followStatus;
|
||||
// }
|
||||
// });
|
||||
|
||||
final res = await PgcHttp.seasonStatus(seasonId);
|
||||
if (res['status']) {
|
||||
final data = res['data'];
|
||||
isFollowed.value = data['follow'] == 1;
|
||||
followStatus.value = data['follow_status'];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -52,8 +52,8 @@ class ActionRowLineItem extends StatelessWidget {
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: theme.colorScheme.outline,
|
||||
)
|
||||
else if (icon != null)
|
||||
icon!,
|
||||
else
|
||||
?icon,
|
||||
AnimatedOpacity(
|
||||
opacity: isLoading ? 0 : 1,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
|
||||
@@ -39,9 +39,9 @@ class WebDav {
|
||||
password: webDavPassword,
|
||||
)
|
||||
..setHeaders({'accept-charset': 'utf-8'})
|
||||
..setConnectTimeout(4000)
|
||||
..setReceiveTimeout(4000)
|
||||
..setSendTimeout(4000);
|
||||
..setConnectTimeout(12000)
|
||||
..setReceiveTimeout(12000)
|
||||
..setSendTimeout(12000);
|
||||
|
||||
await client.mkdirAll(_webdavDirectory);
|
||||
|
||||
|
||||
@@ -324,6 +324,7 @@ class _WebviewPageState extends State<WebviewPage> {
|
||||
SnackBar snackBar = SnackBar(
|
||||
content: const Text('当前网页将要打开外部链接,是否打开'),
|
||||
showCloseIcon: true,
|
||||
persist: false,
|
||||
action: SnackBarAction(
|
||||
label: '打开',
|
||||
onPressed: () => PageUtils.launchURL(url),
|
||||
|
||||
@@ -2,7 +2,8 @@ enum BtmProgressBehavior {
|
||||
alwaysShow('始终展示'),
|
||||
alwaysHide('始终隐藏'),
|
||||
onlyShowFullScreen('仅全屏时展示'),
|
||||
onlyHideFullScreen('仅全屏时隐藏');
|
||||
onlyHideFullScreen('仅全屏时隐藏')
|
||||
;
|
||||
|
||||
final String desc;
|
||||
const BtmProgressBehavior(this.desc);
|
||||
|
||||
@@ -13,7 +13,8 @@ enum FullScreenMode {
|
||||
// 屏幕长宽比 < kScreenRatio 或为竖屏视频时竖屏,否则横屏
|
||||
ratio('屏幕长宽比<$kScreenRatio或为竖屏视频时竖屏,否则横屏'),
|
||||
// 强制重力转屏(仅安卓)
|
||||
gravity('忽略系统方向锁定,强制按重力转屏(仅安卓)');
|
||||
gravity('忽略系统方向锁定,强制按重力转屏(仅安卓)')
|
||||
;
|
||||
|
||||
final String desc;
|
||||
const FullScreenMode(this.desc);
|
||||
|
||||
@@ -31,7 +31,8 @@ enum HwDecType {
|
||||
amf('amf', 'AMF (AMD独占)'),
|
||||
amfCopy('amf-copy', 'AMF (AMD独占) (非直通)'),
|
||||
qsv('qsv', 'Quick Sync Video (Intel独占)'),
|
||||
qsvCopy('qsv-copy', 'Quick Sync Video (Intel独占) (非直通)');
|
||||
qsvCopy('qsv-copy', 'Quick Sync Video (Intel独占) (非直通)')
|
||||
;
|
||||
|
||||
final String hwdec;
|
||||
final String desc;
|
||||
|
||||
@@ -3,7 +3,8 @@ enum PlayRepeat {
|
||||
listOrder('顺序播放'),
|
||||
singleCycle('单个循环'),
|
||||
listCycle('列表循环'),
|
||||
autoPlayRelated('自动连播');
|
||||
autoPlayRelated('自动连播')
|
||||
;
|
||||
|
||||
final String desc;
|
||||
const PlayRepeat(this.desc);
|
||||
|
||||
@@ -8,7 +8,8 @@ enum PlaySpeed {
|
||||
onePointSevenFive(1.75),
|
||||
|
||||
two(2.0),
|
||||
three(3.0);
|
||||
three(3.0)
|
||||
;
|
||||
|
||||
final double value;
|
||||
const PlaySpeed(this.value);
|
||||
|
||||
@@ -9,7 +9,8 @@ enum VideoFitType {
|
||||
none('原始', boxFit: BoxFit.none),
|
||||
scaleDown('限制', boxFit: BoxFit.scaleDown),
|
||||
ratio_4x3('4:3', aspectRatio: 4 / 3),
|
||||
ratio_16x9('16:9', aspectRatio: 16 / 9);
|
||||
ratio_16x9('16:9', aspectRatio: 16 / 9)
|
||||
;
|
||||
|
||||
final String desc;
|
||||
final BoxFit boxFit;
|
||||
|
||||
@@ -150,7 +150,8 @@ enum WebpPreset {
|
||||
photo('photo', '照片', '户外摄影,自然光环境'),
|
||||
drawing('drawing', '绘图', '手绘或线稿,高对比度细节'),
|
||||
icon('icon', '图标', '小型彩色图像'),
|
||||
text('text', '文本', '文字类');
|
||||
text('text', '文本', '文字类')
|
||||
;
|
||||
|
||||
final String flag;
|
||||
final String name;
|
||||
|
||||
@@ -315,10 +315,9 @@ class DownloadService extends GetxService {
|
||||
|
||||
final danmaku = res.removeAt(0).data;
|
||||
for (var i in res) {
|
||||
if (!i.isSuccess) {
|
||||
throw i.toString();
|
||||
if (i.isSuccess) {
|
||||
danmaku.elems.addAll(i.data.elems);
|
||||
}
|
||||
danmaku.elems.addAll(i.data.elems);
|
||||
}
|
||||
res.clear();
|
||||
await danmakuFile.writeAsBytes(danmaku.writeToBuffer());
|
||||
@@ -359,6 +358,10 @@ class DownloadService extends GetxService {
|
||||
|
||||
Future<void> _startDownload(BiliDownloadEntryInfo entry) async {
|
||||
try {
|
||||
if (!await downloadDanmaku(entry: entry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_updateCurStatus(DownloadStatus.getPlayUrl);
|
||||
|
||||
final BiliDownloadMediaInfo mediaFileInfo =
|
||||
@@ -374,15 +377,10 @@ class DownloadService extends GetxService {
|
||||
await videoDir.create(recursive: true);
|
||||
}
|
||||
|
||||
final coverTask = _downloadCover(entry: entry);
|
||||
|
||||
if (!await downloadDanmaku(entry: entry)) {
|
||||
return;
|
||||
}
|
||||
final mediaJsonFile = File(path.join(videoDir.path, _indexFile));
|
||||
await Future.wait([
|
||||
mediaJsonFile.writeAsString(jsonEncode(mediaFileInfo.toJson())),
|
||||
coverTask,
|
||||
_downloadCover(entry: entry),
|
||||
]);
|
||||
|
||||
if (curDownload.value?.cid != entry.cid) {
|
||||
|
||||
@@ -124,6 +124,7 @@ abstract class Accounts {
|
||||
}
|
||||
}
|
||||
|
||||
@pragma("vm:prefer-inline")
|
||||
static Account get(AccountType key) {
|
||||
return accountMode[key.index];
|
||||
}
|
||||
|
||||
@@ -110,6 +110,7 @@ class AccountManager extends Interceptor {
|
||||
Api.ugcUrl,
|
||||
Api.pgcUrl,
|
||||
Api.pugvUrl,
|
||||
Api.tvPlayUrl,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'dart:math' show pow;
|
||||
|
||||
abstract class DurationUtils {
|
||||
abstract final class DurationUtils {
|
||||
static String formatDuration(num? seconds) {
|
||||
if (seconds == null || seconds == 0) {
|
||||
return '00:00';
|
||||
@@ -30,10 +30,10 @@ abstract class DurationUtils {
|
||||
return duration;
|
||||
}
|
||||
|
||||
static String formatDurationBetween(int startMillis, int endMillis) {
|
||||
int diffMillis = endMillis - startMillis;
|
||||
final duration = Duration(milliseconds: diffMillis);
|
||||
static String formatDurationBetween(int startMillis, int endMillis) =>
|
||||
formatTimeDuration(Duration(milliseconds: endMillis - startMillis));
|
||||
|
||||
static String formatTimeDuration(Duration duration) {
|
||||
final inDays = duration.inDays;
|
||||
final daysLeft = inDays % 365;
|
||||
final years = inDays ~/ 365;
|
||||
@@ -42,14 +42,14 @@ abstract class DurationUtils {
|
||||
final hours = duration.inHours % 24;
|
||||
final minutes = duration.inMinutes % 60;
|
||||
|
||||
var format = '';
|
||||
final format = StringBuffer();
|
||||
|
||||
if (years > 0) format += '$years年';
|
||||
if (months > 0) format += '$months月';
|
||||
if (days > 0) format += '$days天';
|
||||
if (hours > 0) format += '$hours小时';
|
||||
if (minutes > 0) format += '$minutes分钟';
|
||||
if (years > 0) format.write('$years年');
|
||||
if (months > 0) format.write('$months月');
|
||||
if (days > 0) format.write('$days天');
|
||||
if (hours > 0) format.write('$hours小时');
|
||||
if (minutes > 0) format.write('$minutes分钟');
|
||||
|
||||
return format;
|
||||
return format.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/foundation.dart' show kDebugMode, debugPrint;
|
||||
import 'package:get/get_utils/get_utils.dart';
|
||||
|
||||
abstract class NumUtils {
|
||||
abstract final class NumUtils {
|
||||
static final _numRegExp = RegExp(r'([\d\.]+)([千万亿])?');
|
||||
|
||||
static int _getUnit(String? unit) {
|
||||
@@ -59,4 +59,24 @@ abstract class NumUtils {
|
||||
return number.toString();
|
||||
}
|
||||
}
|
||||
|
||||
static String formatPositiveDecimal(int number) {
|
||||
if (number < 1000) return number.toString();
|
||||
|
||||
final numStr = number.toString();
|
||||
final length = numStr.length;
|
||||
final sb = StringBuffer();
|
||||
|
||||
int firstLength = length % 3;
|
||||
if (firstLength == 0) firstLength = 3;
|
||||
|
||||
sb.write(numStr.substring(0, firstLength));
|
||||
for (int i = firstLength; i < length; i += 3) {
|
||||
sb
|
||||
..write(',')
|
||||
..write(numStr.substring(i, i + 3));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,11 @@ abstract class ThemeUtils {
|
||||
},
|
||||
),
|
||||
),
|
||||
pageTransitionsTheme: const PageTransitionsTheme(
|
||||
builders: {
|
||||
TargetPlatform.android: ZoomPageTransitionsBuilder(),
|
||||
},
|
||||
),
|
||||
);
|
||||
if (isDark) {
|
||||
if (Pref.isPureBlackTheme) {
|
||||
|
||||
29
pubspec.lock
29
pubspec.lock
@@ -368,10 +368,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: c87dfe3d56f183ffe9106a18aebc6db431fc7c98c31a54b952a77f3d54a85697
|
||||
sha256: a9c30492da18ff84efe2422ba2d319a89942d93e58eb0b73d32abe822ef54b7b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
version: "3.1.3"
|
||||
dbus:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -783,10 +783,11 @@ packages:
|
||||
get:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: get
|
||||
sha256: c79eeb4339f1f3deffd9ec912f8a923834bec55f7b49c9e882b8fef2c139d425
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
path: "."
|
||||
ref: "version_4.7.2"
|
||||
resolved-ref: "579a8978a922e6c57cebd001320f78674e040418"
|
||||
url: "https://github.com/bggRGjQaUbCoE/getx.git"
|
||||
source: git
|
||||
version: "4.7.2"
|
||||
glob:
|
||||
dependency: transitive
|
||||
@@ -912,10 +913,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: image_picker
|
||||
sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041"
|
||||
sha256: "784210112be18ea55f69d7076e2c656a4e24949fa9e76429fe53af0c0f4fa320"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.1"
|
||||
image_picker_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1191,10 +1192,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
version: "1.17.0"
|
||||
mime:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -1733,10 +1734,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.6"
|
||||
version: "0.7.7"
|
||||
tray_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -2012,5 +2013,5 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
sdks:
|
||||
dart: ">=3.9.0 <4.0.0"
|
||||
flutter: "3.35.7"
|
||||
dart: ">=3.10.0 <4.0.0"
|
||||
flutter: "3.38.1"
|
||||
|
||||
10
pubspec.yaml
10
pubspec.yaml
@@ -20,8 +20,8 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
||||
version: 1.1.5+1
|
||||
|
||||
environment:
|
||||
sdk: ">=3.9.0 <4.0.0"
|
||||
flutter: 3.35.7 # update `.fvmrc` config
|
||||
sdk: ">=3.10.0"
|
||||
flutter: 3.38.1 # update `.fvmrc` config
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
@@ -40,7 +40,11 @@ dependencies:
|
||||
# 动态取色
|
||||
dynamic_color: ^1.8.1
|
||||
|
||||
get: ^4.6.6
|
||||
# get: ^4.7.2
|
||||
get:
|
||||
git:
|
||||
url: https://github.com/bggRGjQaUbCoE/getx.git
|
||||
ref: version_4.7.2
|
||||
|
||||
# 网络
|
||||
dio: ^5.7.0
|
||||
|
||||
Reference in New Issue
Block a user