feat: 图片清晰度选择
This commit is contained in:
@ -1,6 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
import 'package:pilipala/common/constants.dart';
|
import 'package:pilipala/common/constants.dart';
|
||||||
|
import 'package:pilipala/utils/storage.dart';
|
||||||
|
|
||||||
|
Box setting = GStrorage.setting;
|
||||||
|
|
||||||
class NetworkImgLayer extends StatelessWidget {
|
class NetworkImgLayer extends StatelessWidget {
|
||||||
final String? src;
|
final String? src;
|
||||||
@ -24,13 +28,17 @@ class NetworkImgLayer extends StatelessWidget {
|
|||||||
this.fadeOutDuration,
|
this.fadeOutDuration,
|
||||||
this.fadeInDuration,
|
this.fadeInDuration,
|
||||||
// 图片质量 默认1%
|
// 图片质量 默认1%
|
||||||
this.quality = 1,
|
this.quality,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
double pr = MediaQuery.of(context).devicePixelRatio;
|
double pr = MediaQuery.of(context).devicePixelRatio;
|
||||||
|
int picQuality = setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10);
|
||||||
|
|
||||||
// double pr = 2;
|
// double pr = 2;
|
||||||
|
print(
|
||||||
|
'${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? picQuality}q.webp');
|
||||||
return src != ''
|
return src != ''
|
||||||
? ClipRRect(
|
? ClipRRect(
|
||||||
clipBehavior: Clip.hardEdge,
|
clipBehavior: Clip.hardEdge,
|
||||||
@ -41,7 +49,7 @@ class NetworkImgLayer extends StatelessWidget {
|
|||||||
: StyleString.imgRadius.x),
|
: StyleString.imgRadius.x),
|
||||||
child: CachedNetworkImage(
|
child: CachedNetworkImage(
|
||||||
imageUrl:
|
imageUrl:
|
||||||
'${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality}q.webp',
|
'${src!.startsWith('//') ? 'https:${src!}' : src!}@${quality ?? picQuality}q.webp',
|
||||||
width: width ?? double.infinity,
|
width: width ?? double.infinity,
|
||||||
height: height ?? double.infinity,
|
height: height ?? double.infinity,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
|
@ -11,10 +11,12 @@ import 'package:pilipala/utils/storage.dart';
|
|||||||
|
|
||||||
class SettingController extends GetxController {
|
class SettingController extends GetxController {
|
||||||
Box user = GStrorage.user;
|
Box user = GStrorage.user;
|
||||||
RxBool userLogin = false.obs;
|
|
||||||
Box userInfoCache = GStrorage.userInfo;
|
|
||||||
Box setting = GStrorage.setting;
|
Box setting = GStrorage.setting;
|
||||||
|
Box userInfoCache = GStrorage.userInfo;
|
||||||
|
|
||||||
|
RxBool userLogin = false.obs;
|
||||||
RxBool feedBackEnable = false.obs;
|
RxBool feedBackEnable = false.obs;
|
||||||
|
RxInt picQuality = 10.obs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
@ -22,6 +24,8 @@ class SettingController extends GetxController {
|
|||||||
userLogin.value = user.get(UserBoxKey.userLogin) ?? false;
|
userLogin.value = user.get(UserBoxKey.userLogin) ?? false;
|
||||||
feedBackEnable.value =
|
feedBackEnable.value =
|
||||||
setting.get(SettingBoxKey.feedBackEnable, defaultValue: false);
|
setting.get(SettingBoxKey.feedBackEnable, defaultValue: false);
|
||||||
|
picQuality.value =
|
||||||
|
setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
loginOut() async {
|
loginOut() async {
|
||||||
|
@ -31,13 +31,19 @@ class _PlaySettingState extends State<PlaySetting> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
TextStyle titleStyle = Theme.of(context).textTheme.titleMedium!;
|
||||||
TextStyle subTitleStyle = Theme.of(context)
|
TextStyle subTitleStyle = Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.labelMedium!
|
.labelMedium!
|
||||||
.copyWith(color: Theme.of(context).colorScheme.outline);
|
.copyWith(color: Theme.of(context).colorScheme.outline);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('播放设置'),
|
centerTitle: false,
|
||||||
|
titleSpacing: 0,
|
||||||
|
title: Text(
|
||||||
|
'播放设置',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: ListView(
|
body: ListView(
|
||||||
children: [
|
children: [
|
||||||
@ -45,15 +51,17 @@ class _PlaySettingState extends State<PlaySetting> {
|
|||||||
title: '自动播放',
|
title: '自动播放',
|
||||||
subTitle: '进入详情页自动播放',
|
subTitle: '进入详情页自动播放',
|
||||||
setKey: SettingBoxKey.autoPlayEnable,
|
setKey: SettingBoxKey.autoPlayEnable,
|
||||||
|
defaultVal: true,
|
||||||
),
|
),
|
||||||
const SetSwitchItem(
|
const SetSwitchItem(
|
||||||
title: '开启硬解',
|
title: '开启硬解',
|
||||||
subTitle: '以较低功耗播放视频',
|
subTitle: '以较低功耗播放视频',
|
||||||
setKey: SettingBoxKey.enableHA,
|
setKey: SettingBoxKey.enableHA,
|
||||||
|
defaultVal: true,
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
dense: false,
|
dense: false,
|
||||||
title: const Text('默认画质'),
|
title: Text('默认画质', style: titleStyle),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
'当前画质' + VideoQualityCode.fromCode(defaultVideoQa)!.description!,
|
'当前画质' + VideoQualityCode.fromCode(defaultVideoQa)!.description!,
|
||||||
style: subTitleStyle,
|
style: subTitleStyle,
|
||||||
@ -78,7 +86,7 @@ class _PlaySettingState extends State<PlaySetting> {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
dense: false,
|
dense: false,
|
||||||
title: const Text('默认音质'),
|
title: Text('默认音质', style: titleStyle),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
'当前音质' + AudioQualityCode.fromCode(defaultAudioQa)!.description!,
|
'当前音质' + AudioQualityCode.fromCode(defaultAudioQa)!.description!,
|
||||||
style: subTitleStyle,
|
style: subTitleStyle,
|
||||||
@ -103,7 +111,7 @@ class _PlaySettingState extends State<PlaySetting> {
|
|||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
dense: false,
|
dense: false,
|
||||||
title: const Text('默认解码格式'),
|
title: Text('默认解码格式', style: titleStyle),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
'当前解码格式' +
|
'当前解码格式' +
|
||||||
VideoDecodeFormatsCode.fromCode(defaultDecode)!.description!,
|
VideoDecodeFormatsCode.fromCode(defaultDecode)!.description!,
|
||||||
|
127
lib/pages/setting/style_setting.dart
Normal file
127
lib/pages/setting/style_setting.dart
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:pilipala/utils/storage.dart';
|
||||||
|
|
||||||
|
import 'controller.dart';
|
||||||
|
|
||||||
|
class StyleSetting extends StatefulWidget {
|
||||||
|
const StyleSetting({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StyleSetting> createState() => _StyleSettingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _StyleSettingState extends State<StyleSetting> {
|
||||||
|
final SettingController settingController = Get.put(SettingController());
|
||||||
|
Box setting = GStrorage.setting;
|
||||||
|
late int picQuality;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
picQuality = setting.get(SettingBoxKey.defaultPicQa, defaultValue: 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
TextStyle titleStyle = Theme.of(context).textTheme.titleMedium!;
|
||||||
|
TextStyle subTitleStyle = Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelMedium!
|
||||||
|
.copyWith(color: Theme.of(context).colorScheme.outline);
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
centerTitle: false,
|
||||||
|
titleSpacing: 0,
|
||||||
|
title: Text(
|
||||||
|
'外观设置',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
children: [
|
||||||
|
Obx(
|
||||||
|
() => ListTile(
|
||||||
|
enableFeedback: true,
|
||||||
|
onTap: () => settingController.onOpenFeedBack(),
|
||||||
|
title: const Text('震动反馈'),
|
||||||
|
subtitle: Text('请确定手机设置中已开启震动反馈', style: subTitleStyle),
|
||||||
|
trailing: Transform.scale(
|
||||||
|
scale: 0.8,
|
||||||
|
child: Switch(
|
||||||
|
thumbIcon: MaterialStateProperty.resolveWith<Icon?>(
|
||||||
|
(Set<MaterialState> states) {
|
||||||
|
if (states.isNotEmpty &&
|
||||||
|
states.first == MaterialState.selected) {
|
||||||
|
return const Icon(Icons.done);
|
||||||
|
}
|
||||||
|
return null; // All other states will use the default thumbIcon.
|
||||||
|
}),
|
||||||
|
value: settingController.feedBackEnable.value,
|
||||||
|
onChanged: (value) => settingController.onOpenFeedBack()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
dense: false,
|
||||||
|
onTap: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (context, StateSetter setState) {
|
||||||
|
final SettingController settingController =
|
||||||
|
Get.put(SettingController());
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text('图片清晰度 - $picQuality%', style: titleStyle),
|
||||||
|
contentPadding: const EdgeInsets.only(
|
||||||
|
top: 20, left: 8, right: 8, bottom: 8),
|
||||||
|
content: SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: Slider(
|
||||||
|
value: picQuality.toDouble(),
|
||||||
|
min: 10,
|
||||||
|
max: 100,
|
||||||
|
divisions: 9,
|
||||||
|
label: '$picQuality%',
|
||||||
|
onChanged: (double val) {
|
||||||
|
picQuality = val.toInt();
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Get.back(),
|
||||||
|
child: const Text('取消')),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
setting.put(
|
||||||
|
SettingBoxKey.defaultPicQa, picQuality);
|
||||||
|
Get.back();
|
||||||
|
settingController.picQuality.value = picQuality;
|
||||||
|
},
|
||||||
|
child: const Text('确定'),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
title: Text('图片质量', style: titleStyle),
|
||||||
|
subtitle: Text('选择合适的图片清晰度,上限100%', style: subTitleStyle),
|
||||||
|
trailing: Obx(
|
||||||
|
() => Text(
|
||||||
|
'${settingController.picQuality.value}%',
|
||||||
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -14,42 +14,25 @@ class SettingPage extends StatelessWidget {
|
|||||||
final SettingController settingController = Get.put(SettingController());
|
final SettingController settingController = Get.put(SettingController());
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('设置'),
|
centerTitle: false,
|
||||||
|
titleSpacing: 0,
|
||||||
|
title: Text(
|
||||||
|
'设置',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
Obx(
|
|
||||||
() => ListTile(
|
|
||||||
enableFeedback: true,
|
|
||||||
onTap: () => settingController.onOpenFeedBack(),
|
|
||||||
title: const Text('震动反馈'),
|
|
||||||
subtitle: Text('请确定手机设置中已开启震动反馈', style: subTitleStyle),
|
|
||||||
trailing: Transform.scale(
|
|
||||||
scale: 0.8,
|
|
||||||
child: Switch(
|
|
||||||
thumbIcon: MaterialStateProperty.resolveWith<Icon?>(
|
|
||||||
(Set<MaterialState> states) {
|
|
||||||
if (states.isNotEmpty &&
|
|
||||||
states.first == MaterialState.selected) {
|
|
||||||
return const Icon(Icons.done);
|
|
||||||
}
|
|
||||||
return null; // All other states will use the default thumbIcon.
|
|
||||||
}),
|
|
||||||
value: settingController.feedBackEnable.value,
|
|
||||||
onChanged: (value) => settingController.onOpenFeedBack()),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
onTap: () => Get.toNamed('/playSetting'),
|
onTap: () => Get.toNamed('/playSetting'),
|
||||||
dense: false,
|
dense: false,
|
||||||
title: const Text('播放设置'),
|
title: const Text('播放设置'),
|
||||||
),
|
),
|
||||||
// ListTile(
|
ListTile(
|
||||||
// onTap: () {},
|
onTap: () => Get.toNamed('/styleSetting'),
|
||||||
// dense: false,
|
dense: false,
|
||||||
// title: const Text('外观设置'),
|
title: const Text('外观设置'),
|
||||||
// ),
|
),
|
||||||
// ListTile(
|
// ListTile(
|
||||||
// onTap: () {},
|
// onTap: () {},
|
||||||
// dense: false,
|
// dense: false,
|
||||||
|
@ -6,11 +6,13 @@ class SetSwitchItem extends StatefulWidget {
|
|||||||
final String? title;
|
final String? title;
|
||||||
final String? subTitle;
|
final String? subTitle;
|
||||||
final String? setKey;
|
final String? setKey;
|
||||||
|
final bool? defaultVal;
|
||||||
|
|
||||||
const SetSwitchItem({
|
const SetSwitchItem({
|
||||||
this.title,
|
this.title,
|
||||||
this.subTitle,
|
this.subTitle,
|
||||||
this.setKey,
|
this.setKey,
|
||||||
|
this.defaultVal,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@ -26,11 +28,12 @@ class _SetSwitchItemState extends State<SetSwitchItem> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
val = Setting.get(widget.setKey, defaultValue: false);
|
val = Setting.get(widget.setKey, defaultValue: widget.defaultVal ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
TextStyle titleStyle = Theme.of(context).textTheme.titleMedium!;
|
||||||
TextStyle subTitleStyle = Theme.of(context)
|
TextStyle subTitleStyle = Theme.of(context)
|
||||||
.textTheme
|
.textTheme
|
||||||
.labelMedium!
|
.labelMedium!
|
||||||
@ -40,7 +43,7 @@ class _SetSwitchItemState extends State<SetSwitchItem> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
Setting.put(widget.setKey, !val);
|
Setting.put(widget.setKey, !val);
|
||||||
},
|
},
|
||||||
title: Text(widget.title!),
|
title: Text(widget.title!, style: titleStyle),
|
||||||
subtitle: widget.subTitle != null
|
subtitle: widget.subTitle != null
|
||||||
? Text(widget.subTitle!, style: subTitleStyle)
|
? Text(widget.subTitle!, style: subTitleStyle)
|
||||||
: null,
|
: null,
|
||||||
|
@ -15,6 +15,7 @@ import 'package:pilipala/pages/preview/index.dart';
|
|||||||
import 'package:pilipala/pages/search/index.dart';
|
import 'package:pilipala/pages/search/index.dart';
|
||||||
import 'package:pilipala/pages/searchResult/index.dart';
|
import 'package:pilipala/pages/searchResult/index.dart';
|
||||||
import 'package:pilipala/pages/setting/play_setting.dart';
|
import 'package:pilipala/pages/setting/play_setting.dart';
|
||||||
|
import 'package:pilipala/pages/setting/style_setting.dart';
|
||||||
import 'package:pilipala/pages/video/detail/index.dart';
|
import 'package:pilipala/pages/video/detail/index.dart';
|
||||||
import 'package:pilipala/pages/video/detail/replyReply/index.dart';
|
import 'package:pilipala/pages/video/detail/replyReply/index.dart';
|
||||||
import 'package:pilipala/pages/webview/index.dart';
|
import 'package:pilipala/pages/webview/index.dart';
|
||||||
@ -71,6 +72,8 @@ class Routes {
|
|||||||
GetPage(name: '/replyReply', page: () => const VideoReplyReplyPanel()),
|
GetPage(name: '/replyReply', page: () => const VideoReplyReplyPanel()),
|
||||||
|
|
||||||
// 播放设置
|
// 播放设置
|
||||||
GetPage(name: '/playSetting', page: () => const PlaySetting())
|
GetPage(name: '/playSetting', page: () => const PlaySetting()),
|
||||||
|
|
||||||
|
GetPage(name: '/styleSetting', page: () => const StyleSetting()),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ class SettingBoxKey {
|
|||||||
static const String autoUpgradeEnable = 'autoUpgradeEnable';
|
static const String autoUpgradeEnable = 'autoUpgradeEnable';
|
||||||
static const String autoPlayEnable = 'autoPlayEnable';
|
static const String autoPlayEnable = 'autoPlayEnable';
|
||||||
static const String enableHA = 'enableHA';
|
static const String enableHA = 'enableHA';
|
||||||
|
static const String defaultPicQa = 'defaultPicQa';
|
||||||
|
|
||||||
static const String danmakuEnable = 'danmakuEnable';
|
static const String danmakuEnable = 'danmakuEnable';
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user