add lint rules
This commit is contained in:
parent
6842d323e8
commit
be634e763a
|
@ -0,0 +1,8 @@
|
|||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
avoid_print: false
|
||||
unnecessary_this: false
|
||||
file_names: false
|
||||
constant_identifier_names: false
|
|
@ -360,7 +360,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 5BU82VSTV4;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
|
@ -492,7 +492,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 5BU82VSTV4;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
|
@ -516,7 +516,7 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = 5BU82VSTV4;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
|
|
|
@ -7,7 +7,7 @@ import 'package:flutter/services.dart';
|
|||
// 由于Flutter的EventChannel只能订阅一次, 且为了和golang的的通信, 这里实现了多次订阅的分发和平铺
|
||||
// 根据eventName订阅和取消订阅
|
||||
|
||||
var _eventChannel = EventChannel("flatEvent");
|
||||
var _eventChannel = const EventChannel("flatEvent");
|
||||
StreamSubscription? _eventChannelListen;
|
||||
|
||||
Map<void Function(String args), String> _eventMap = {};
|
||||
|
@ -28,7 +28,7 @@ void unregisterEvent(void Function(String args) eventHandler) {
|
|||
throw 'no register';
|
||||
}
|
||||
_eventMap.remove(eventHandler);
|
||||
if (_eventMap.length == 0) {
|
||||
if (_eventMap.isEmpty) {
|
||||
_eventChannelListen?.cancel();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ void defaultToast(BuildContext context, String title) {
|
|||
position: StyledToastPosition.center,
|
||||
animation: StyledToastAnimation.scale,
|
||||
reverseAnimation: StyledToastAnimation.fade,
|
||||
duration: Duration(seconds: 4),
|
||||
animDuration: Duration(seconds: 1),
|
||||
duration: const Duration(seconds: 4),
|
||||
animDuration: const Duration(seconds: 1),
|
||||
curve: Curves.elasticOut,
|
||||
reverseCurve: Curves.linear,
|
||||
);
|
||||
|
@ -33,22 +33,20 @@ Future<bool> confirmDialog(
|
|||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: new SingleChildScrollView(
|
||||
child: new ListBody(
|
||||
children: <Widget>[
|
||||
new Text(content),
|
||||
],
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: <Widget>[Text(content)],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
new MaterialButton(
|
||||
child: new Text('取消'),
|
||||
MaterialButton(
|
||||
child: const Text('取消'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(false);
|
||||
},
|
||||
),
|
||||
new MaterialButton(
|
||||
child: new Text('确定'),
|
||||
MaterialButton(
|
||||
child: const Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
|
@ -61,35 +59,36 @@ Future<bool> confirmDialog(
|
|||
/// 显示一个消息提示框
|
||||
Future alertDialog(BuildContext context, String title, String content) {
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: new SingleChildScrollView(
|
||||
child: new ListBody(
|
||||
children: <Widget>[
|
||||
new Text(content),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
new MaterialButton(
|
||||
child: new Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
));
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
Text(content),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
MaterialButton(
|
||||
child: const Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// stream-filter的替代方法
|
||||
List<T> filteredList<T>(List<T> list, bool Function(T) filter) {
|
||||
List<T> result = [];
|
||||
list.forEach((element) {
|
||||
for (var element in list) {
|
||||
if (filter(element)) {
|
||||
result.add(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -197,7 +196,7 @@ Future<String?> displayTextInputDialog(BuildContext context,
|
|||
},
|
||||
),
|
||||
MaterialButton(
|
||||
child: Text('确认'),
|
||||
child: const Text('确认'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(_controller.text);
|
||||
},
|
||||
|
@ -258,12 +257,10 @@ Future<String?> inputString(BuildContext context, String title,
|
|||
child: ListBody(
|
||||
children: [
|
||||
Text(title),
|
||||
Container(
|
||||
child: TextField(
|
||||
controller: _textEditController,
|
||||
decoration: new InputDecoration(
|
||||
labelText: "$hint",
|
||||
),
|
||||
TextField(
|
||||
controller: _textEditController,
|
||||
decoration: InputDecoration(
|
||||
labelText: hint,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
@ -275,13 +272,13 @@ Future<String?> inputString(BuildContext context, String title,
|
|||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text('取消'),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
MaterialButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, _textEditController.text);
|
||||
},
|
||||
child: Text('确定'),
|
||||
child: const Text('确定'),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
@ -13,7 +13,7 @@ class Method {
|
|||
Method._();
|
||||
|
||||
/// channel
|
||||
MethodChannel _channel = MethodChannel("method");
|
||||
final MethodChannel _channel = const MethodChannel("method");
|
||||
|
||||
/// 平铺调用, 为了直接与golang进行通信
|
||||
Future<dynamic> _flatInvoke(String method, dynamic params) {
|
||||
|
|
|
@ -29,7 +29,7 @@ Future<void> _chooseAndroidDisplayMode(BuildContext context) async {
|
|||
list.addAll(_modes);
|
||||
String? result = await chooseListDialog<String>(context, "安卓屏幕刷新率", list);
|
||||
if (result != null) {
|
||||
await method.saveProperty(_propertyName, "$result");
|
||||
await method.saveProperty(_propertyName, result);
|
||||
_androidDisplayMode = result;
|
||||
await _changeMode();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pikapika/basic/Common.dart';
|
||||
import 'package:pikapika/basic/Cross.dart';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/// 多线程下载并发数
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pikapika/basic/Common.dart';
|
||||
import 'package:pikapika/basic/Method.dart';
|
||||
|
|
|
@ -67,6 +67,8 @@ void switchFullScreenUI() {
|
|||
case FullScreenUI.ALL:
|
||||
list.clear();
|
||||
break;
|
||||
case FullScreenUI.NO:
|
||||
break;
|
||||
}
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
SystemChrome.setEnabledSystemUIOverlays(list);
|
||||
|
@ -78,7 +80,7 @@ Widget fullScreenUISetting() {
|
|||
return StatefulBuilder(
|
||||
builder: (BuildContext context, void Function(void Function()) setState) {
|
||||
return ListTile(
|
||||
title: Text("全屏UI"),
|
||||
title: const Text("全屏UI"),
|
||||
subtitle: Text(currentFullScreenUIName()),
|
||||
onTap: () async {
|
||||
await chooseFullScreenUI(context);
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
/// 相册模式下预加载图片数量
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pikapika/basic/Method.dart';
|
||||
|
||||
import '../Common.dart';
|
||||
|
||||
const galleryPrePreloadCount = 1;
|
||||
const galleryPreloadCount = 2;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../Method.dart';
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../Common.dart';
|
||||
|
|
|
@ -9,6 +9,7 @@ late String _currentProxy;
|
|||
|
||||
Future<String?> initProxy() async {
|
||||
_currentProxy = await method.getProxy();
|
||||
return null;
|
||||
}
|
||||
|
||||
String currentProxyName() {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:multi_select_flutter/dialog/mult_select_dialog.dart';
|
||||
import 'package:multi_select_flutter/multi_select_flutter.dart';
|
||||
|
||||
import '../Method.dart';
|
||||
|
@ -33,11 +32,11 @@ Future<void> _chooseShadowCategories(BuildContext context) async {
|
|||
context: context,
|
||||
builder: (ctx) {
|
||||
var initialValue = <String>[];
|
||||
shadowCategories.forEach((element) {
|
||||
for (var element in shadowCategories) {
|
||||
if (shadowCategories.contains(element)) {
|
||||
initialValue.add(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
return MultiSelectDialog<String>(
|
||||
title: Text('封印'),
|
||||
searchHint: '搜索',
|
||||
|
|
|
@ -380,7 +380,7 @@ Future<dynamic> chooseTheme(BuildContext buildContext) async {
|
|||
)
|
||||
));
|
||||
return SimpleDialog(
|
||||
title: Text("选择主题"),
|
||||
title: const Text("选择主题"),
|
||||
children: list,
|
||||
);
|
||||
})
|
||||
|
|
|
@ -31,7 +31,7 @@ Future<void> _chooseTimeZone(BuildContext context) async {
|
|||
result = result.substring(1);
|
||||
}
|
||||
_timeOffsetHour = int.parse(result);
|
||||
await method.saveProperty(_propertyName, "$result");
|
||||
await method.saveProperty(_propertyName, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ const _releasesUrl = "https://github.com/niuhuan/pikapika/releases";
|
|||
|
||||
// 关于
|
||||
class AboutScreen extends StatefulWidget {
|
||||
const AboutScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _AboutScreenState();
|
||||
}
|
||||
|
@ -40,11 +42,11 @@ class _AboutScreenState extends State<AboutScreen> {
|
|||
var _dirty = dirtyVersion();
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('关于'),
|
||||
title: const Text('关于'),
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
Container(
|
||||
SizedBox(
|
||||
width: min / 2,
|
||||
height: min / 2,
|
||||
child: Center(
|
||||
|
|
|
@ -13,6 +13,8 @@ import 'components/ContentLoading.dart';
|
|||
|
||||
// 账户设置
|
||||
class AccountScreen extends StatefulWidget {
|
||||
const AccountScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AccountScreenState createState() => _AccountScreenState();
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ class _AppScreenState extends State<AppScreen> {
|
|||
}
|
||||
|
||||
static const List<Widget> _widgetOptions = <Widget>[
|
||||
const CategoriesScreen(),
|
||||
const SpaceScreen(),
|
||||
CategoriesScreen(),
|
||||
SpaceScreen(),
|
||||
];
|
||||
|
||||
late int _selectedIndex = 0;
|
||||
|
|
|
@ -18,7 +18,7 @@ import 'components/Images.dart';
|
|||
|
||||
// 分类
|
||||
class CategoriesScreen extends StatefulWidget {
|
||||
const CategoriesScreen();
|
||||
const CategoriesScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _CategoriesScreenState();
|
||||
|
@ -41,7 +41,7 @@ class _CategoriesScreenState extends State<CategoriesScreen> {
|
|||
},
|
||||
buildDefaultAppBar: (BuildContext context) {
|
||||
return AppBar(
|
||||
title: new Text('分类'),
|
||||
title: Text('分类'),
|
||||
actions: [
|
||||
shadowCategoriesActionButton(context),
|
||||
_searchBar.getSearchAction(context),
|
||||
|
@ -55,11 +55,11 @@ class _CategoriesScreenState extends State<CategoriesScreen> {
|
|||
Future<List<Category>> _fetch() async {
|
||||
List<Category> categories = await method.categories();
|
||||
storedCategories = [];
|
||||
categories.forEach((element) {
|
||||
for (var element in categories) {
|
||||
if (!element.isWeb) {
|
||||
storedCategories.add(element.title);
|
||||
}
|
||||
});
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ class _CategoriesScreenState extends State<CategoriesScreen> {
|
|||
list.add(
|
||||
GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: blockSize,
|
||||
child: Column(
|
||||
children: [
|
||||
|
@ -221,7 +221,7 @@ class _CategoriesScreenState extends State<CategoriesScreen> {
|
|||
list.add(
|
||||
GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: blockSize,
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
|
@ -8,6 +8,8 @@ import 'components/ContentLoading.dart';
|
|||
|
||||
// 清理
|
||||
class CleanScreen extends StatefulWidget {
|
||||
const CleanScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _CleanScreenState();
|
||||
}
|
||||
|
@ -44,15 +46,15 @@ class _CleanScreenState extends State<CleanScreen> {
|
|||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('清理'),
|
||||
title: const Text('清理'),
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(8),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: _cleanResult != "" ? Text(_cleanResult) : Container(),
|
||||
),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: FitButton(
|
||||
text: '清理网络缓存',
|
||||
|
@ -61,7 +63,7 @@ class _CleanScreenState extends State<CleanScreen> {
|
|||
},
|
||||
),
|
||||
),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: FitButton(
|
||||
text: '清理图片缓存',
|
||||
|
@ -70,7 +72,7 @@ class _CleanScreenState extends State<CleanScreen> {
|
|||
},
|
||||
),
|
||||
),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: 50,
|
||||
child: FitButton(
|
||||
text: '清理全部缓存',
|
||||
|
|
|
@ -151,19 +151,19 @@ class _ComicInfoScreenState extends State<ComicInfoScreen> with RouteAware {
|
|||
onLongPress: () {
|
||||
confirmCopy(
|
||||
context,
|
||||
"${_comicInfo.creator.name}",
|
||||
_comicInfo.creator.name,
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
"${_comicInfo.creator.name}",
|
||||
style: TextStyle(
|
||||
_comicInfo.creator.name,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
const TextSpan(
|
||||
text: " ",
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
|
@ -195,8 +195,8 @@ class _ComicInfoScreenState extends State<ComicInfoScreen> with RouteAware {
|
|||
confirmCopy(context, _comicInfo.chineseTeam);
|
||||
},
|
||||
child: Text(
|
||||
"${_comicInfo.chineseTeam}",
|
||||
style: TextStyle(
|
||||
_comicInfo.chineseTeam,
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey,
|
||||
),
|
||||
|
@ -300,15 +300,13 @@ class _ComicInfoScreenState extends State<ComicInfoScreen> with RouteAware {
|
|||
alignment: WrapAlignment.spaceAround,
|
||||
children: [
|
||||
..._epList.map((e) {
|
||||
return Container(
|
||||
child: MaterialButton(
|
||||
onPressed: () {
|
||||
_push(_comicInfo, _epList, e.order, null);
|
||||
},
|
||||
color: Colors.white,
|
||||
child:
|
||||
Text(e.title, style: TextStyle(color: Colors.black)),
|
||||
),
|
||||
return MaterialButton(
|
||||
onPressed: () {
|
||||
_push(_comicInfo, _epList, e.order, null);
|
||||
},
|
||||
color: Colors.white,
|
||||
child:
|
||||
Text(e.title, style: TextStyle(color: Colors.black)),
|
||||
);
|
||||
}),
|
||||
],
|
||||
|
|
|
@ -3,7 +3,6 @@ import 'dart:io';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:pikapika/basic/Common.dart';
|
||||
import 'package:pikapika/basic/Entities.dart';
|
||||
import 'package:pikapika/basic/Method.dart';
|
||||
import 'package:pikapika/basic/config/AutoFullScreen.dart';
|
||||
|
@ -76,10 +75,10 @@ class _ComicReaderScreenState extends State<ComicReaderScreen> {
|
|||
}
|
||||
|
||||
FutureOr<dynamic> _onChangeEp(int epOrder) {
|
||||
var orderMap = Map<int, Ep>();
|
||||
widget.epList.forEach((element) {
|
||||
var orderMap = <int, Ep>{};
|
||||
for (var element in widget.epList) {
|
||||
orderMap[element.order] = element;
|
||||
});
|
||||
}
|
||||
if (orderMap.containsKey(epOrder)) {
|
||||
_replacement = true;
|
||||
Navigator.of(context).pushReplacement(
|
||||
|
@ -124,11 +123,11 @@ class _ComicReaderScreenState extends State<ComicReaderScreen> {
|
|||
@override
|
||||
void initState() {
|
||||
// EP
|
||||
widget.epList.forEach((element) {
|
||||
for (var element in widget.epList) {
|
||||
if (element.order == widget.currentEpOrder) {
|
||||
_ep = element;
|
||||
}
|
||||
});
|
||||
}
|
||||
// INIT
|
||||
_future = _load();
|
||||
super.initState();
|
||||
|
@ -177,13 +176,13 @@ class _ComicReaderScreenState extends State<ComicReaderScreen> {
|
|||
: AppBar(
|
||||
title: Text("${_ep.title} - ${widget.comicInfo.title}"),
|
||||
),
|
||||
body: ContentLoading(label: '加载中'),
|
||||
body: const ContentLoading(label: '加载中'),
|
||||
);
|
||||
}
|
||||
var epNameMap = Map<int, String>();
|
||||
widget.epList.forEach((element) {
|
||||
var epNameMap = <int, String>{};
|
||||
for (var element in widget.epList) {
|
||||
epNameMap[element.order] = element.title;
|
||||
});
|
||||
}
|
||||
return Scaffold(
|
||||
body: ImageReader(
|
||||
ImageReaderStruct(
|
||||
|
|
|
@ -32,7 +32,7 @@ class ComicsScreen extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _ComicsScreenState extends State<ComicsScreen> {
|
||||
late SearchBar _categorySearchBar = SearchBar(
|
||||
late final SearchBar _categorySearchBar = SearchBar(
|
||||
hintText: '搜索分类 - ${categoryTitle(widget.category)}',
|
||||
inBar: false,
|
||||
setState: setState,
|
||||
|
@ -49,7 +49,7 @@ class _ComicsScreenState extends State<ComicsScreen> {
|
|||
},
|
||||
buildDefaultAppBar: (BuildContext context) {
|
||||
return AppBar(
|
||||
title: new Text(categoryTitle(widget.category)),
|
||||
title: Text(categoryTitle(widget.category)),
|
||||
actions: [
|
||||
shadowCategoriesActionButton(context),
|
||||
chooseLayoutActionButton(context),
|
||||
|
|
|
@ -28,7 +28,8 @@ class CommentScreen extends StatefulWidget {
|
|||
final String mainId;
|
||||
final CommentBase comment;
|
||||
|
||||
const CommentScreen(this.mainType, this.mainId, this.comment);
|
||||
const CommentScreen(this.mainType, this.mainId, this.comment, {Key? key})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _CommentScreenState();
|
||||
|
|
|
@ -25,8 +25,8 @@ class DownloadConfirmScreen extends StatefulWidget {
|
|||
|
||||
class _DownloadConfirmScreenState extends State<DownloadConfirmScreen> {
|
||||
DownloadComic? _task; // 之前的下载任务
|
||||
List<int> _taskedEps = []; // 已经下载的EP
|
||||
List<int> _selectedEps = []; // 选中的EP
|
||||
final List<int> _taskedEps = []; // 已经下载的EP
|
||||
final List<int> _selectedEps = []; // 选中的EP
|
||||
late Future f = _load();
|
||||
|
||||
Future<dynamic> _load() async {
|
||||
|
@ -41,11 +41,11 @@ class _DownloadConfirmScreenState extends State<DownloadConfirmScreen> {
|
|||
void _selectAll() {
|
||||
setState(() {
|
||||
_selectedEps.clear();
|
||||
widget.epList.forEach((element) {
|
||||
for (var element in widget.epList) {
|
||||
if (!_taskedEps.contains(element.order)) {
|
||||
_selectedEps.add(element.order);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class _DownloadConfirmScreenState extends State<DownloadConfirmScreen> {
|
|||
};
|
||||
// 下载EP列表
|
||||
List<Map<String, dynamic>> list = [];
|
||||
widget.epList.forEach((element) {
|
||||
for (var element in widget.epList) {
|
||||
if (_selectedEps.contains(element.order)) {
|
||||
list.add({
|
||||
"comicId": widget.comicInfo.id,
|
||||
|
@ -85,7 +85,7 @@ class _DownloadConfirmScreenState extends State<DownloadConfirmScreen> {
|
|||
"title": element.title,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// 如果之前下载过就将EP加入下载
|
||||
// 如果之前没有下载过就创建下载
|
||||
if (_task != null) {
|
||||
|
|
|
@ -20,10 +20,11 @@ class DownloadExportToFileScreen extends StatefulWidget {
|
|||
final String comicId;
|
||||
final String comicTitle;
|
||||
|
||||
DownloadExportToFileScreen({
|
||||
const DownloadExportToFileScreen({
|
||||
required this.comicId,
|
||||
required this.comicTitle,
|
||||
});
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _DownloadExportToFileScreenState();
|
||||
|
@ -233,7 +234,7 @@ class _DownloadExportToFileScreenState
|
|||
return;
|
||||
}
|
||||
if (!(await Permission.storage.request()).isGranted) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
setState(() {
|
||||
|
|
|
@ -15,11 +15,12 @@ class DownloadExportToSocketScreen extends StatefulWidget {
|
|||
final String comicId;
|
||||
final String comicTitle;
|
||||
|
||||
DownloadExportToSocketScreen({
|
||||
const DownloadExportToSocketScreen({
|
||||
required this.task,
|
||||
required this.comicId,
|
||||
required this.comicTitle,
|
||||
});
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _DownloadExportToSocketScreenState();
|
||||
|
@ -28,7 +29,7 @@ class DownloadExportToSocketScreen extends StatefulWidget {
|
|||
class _DownloadExportToSocketScreenState
|
||||
extends State<DownloadExportToSocketScreen> {
|
||||
late Future<int> _future = method.exportComicUsingSocket(widget.comicId);
|
||||
late Future<String> _ipFuture = method.clientIpSet();
|
||||
late final Future<String> _ipFuture = method.clientIpSet();
|
||||
|
||||
late String exportMessage = "";
|
||||
|
||||
|
@ -89,16 +90,16 @@ class _DownloadExportToSocketScreenState
|
|||
builder: (BuildContext context,
|
||||
AsyncSnapshot<String> snapshot) {
|
||||
if (snapshot.hasError) {
|
||||
return Text('获取IP失败');
|
||||
return const Text('获取IP失败');
|
||||
}
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return Text('正在获取IP');
|
||||
return const Text('正在获取IP');
|
||||
}
|
||||
return Text('${snapshot.data}');
|
||||
},
|
||||
),
|
||||
Text('端口号:${snapshot.data}'),
|
||||
Text('$exportMessage'),
|
||||
Text(exportMessage),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:filesystem_picker/filesystem_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:pikapika/basic/Channels.dart';
|
||||
import 'package:pikapika/basic/Common.dart';
|
||||
import 'package:pikapika/basic/Method.dart';
|
||||
|
@ -13,6 +11,8 @@ import 'components/ContentLoading.dart';
|
|||
|
||||
// 导入
|
||||
class DownloadImportScreen extends StatefulWidget {
|
||||
const DownloadImportScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _DownloadImportScreenState();
|
||||
}
|
||||
|
|
|
@ -19,10 +19,11 @@ class DownloadInfoScreen extends StatefulWidget {
|
|||
final String comicId;
|
||||
final String comicTitle;
|
||||
|
||||
DownloadInfoScreen({
|
||||
const DownloadInfoScreen({
|
||||
required this.comicId,
|
||||
required this.comicTitle,
|
||||
});
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _DownloadInfoScreenState();
|
||||
|
@ -143,15 +144,13 @@ class _DownloadInfoScreenState extends State<DownloadInfoScreen>
|
|||
},
|
||||
),
|
||||
..._epList.map((e) {
|
||||
return Container(
|
||||
child: MaterialButton(
|
||||
onPressed: () {
|
||||
_push(_task, _epList, e.epOrder, null);
|
||||
},
|
||||
color: Colors.white,
|
||||
child: Text(e.title,
|
||||
style: TextStyle(color: Colors.black)),
|
||||
),
|
||||
return MaterialButton(
|
||||
onPressed: () {
|
||||
_push(_task, _epList, e.epOrder, null);
|
||||
},
|
||||
color: Colors.white,
|
||||
child: Text(e.title,
|
||||
style: const TextStyle(color: Colors.black)),
|
||||
);
|
||||
}),
|
||||
],
|
||||
|
|
|
@ -13,6 +13,8 @@ import 'components/DownloadInfoCard.dart';
|
|||
|
||||
// 下载列表
|
||||
class DownloadListScreen extends StatefulWidget {
|
||||
const DownloadListScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _DownloadListScreenState();
|
||||
}
|
||||
|
@ -25,15 +27,13 @@ class _DownloadListScreenState extends State<DownloadListScreen> {
|
|||
void _onMessageChange(String event) {
|
||||
print("EVENT");
|
||||
print(event);
|
||||
if (event is String) {
|
||||
try {
|
||||
setState(() {
|
||||
_downloading = DownloadComic.fromJson(json.decode(event));
|
||||
});
|
||||
} catch (e, s) {
|
||||
print(e);
|
||||
print(s);
|
||||
}
|
||||
try {
|
||||
setState(() {
|
||||
_downloading = DownloadComic.fromJson(json.decode(event));
|
||||
});
|
||||
} catch (e, s) {
|
||||
print(e);
|
||||
print(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,10 +76,10 @@ class _DownloadReaderScreenState extends State<DownloadReaderScreen> {
|
|||
}
|
||||
|
||||
FutureOr<dynamic> _onChangeEp(int epOrder) {
|
||||
var orderMap = Map<int, DownloadEp>();
|
||||
widget.epList.forEach((element) {
|
||||
var orderMap = <int, DownloadEp>{};
|
||||
for (var element in widget.epList) {
|
||||
orderMap[element.epOrder] = element;
|
||||
});
|
||||
}
|
||||
if (orderMap.containsKey(epOrder)) {
|
||||
_replacement = true;
|
||||
Navigator.of(context).pushReplacement(
|
||||
|
@ -114,11 +114,11 @@ class _DownloadReaderScreenState extends State<DownloadReaderScreen> {
|
|||
@override
|
||||
void initState() {
|
||||
// EP
|
||||
widget.epList.forEach((element) {
|
||||
for (var element in widget.epList) {
|
||||
if (element.epOrder == widget.currentEpOrder) {
|
||||
_ep = element;
|
||||
}
|
||||
});
|
||||
}
|
||||
// INIT
|
||||
_future = _load();
|
||||
super.initState();
|
||||
|
@ -169,10 +169,10 @@ class _DownloadReaderScreenState extends State<DownloadReaderScreen> {
|
|||
body: ContentLoading(label: '加载中'),
|
||||
);
|
||||
}
|
||||
var epNameMap = Map<int, String>();
|
||||
widget.epList.forEach((element) {
|
||||
var epNameMap = <int, String>{};
|
||||
for (var element in widget.epList) {
|
||||
epNameMap[element.epOrder] = element.title;
|
||||
});
|
||||
}
|
||||
return Scaffold(
|
||||
body: ImageReader(
|
||||
ImageReaderStruct(
|
||||
|
|
|
@ -5,6 +5,8 @@ import 'components/ComicPager.dart';
|
|||
|
||||
// 收藏的漫画
|
||||
class FavouritePaperScreen extends StatefulWidget {
|
||||
const FavouritePaperScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _FavouritePaperScreen();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import 'package:pikapika/screens/components/Images.dart';
|
|||
class FilePhotoViewScreen extends StatelessWidget {
|
||||
final String filePath;
|
||||
|
||||
FilePhotoViewScreen(this.filePath);
|
||||
const FilePhotoViewScreen(this.filePath, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Scaffold(
|
||||
|
|
|
@ -18,7 +18,7 @@ class GameDownloadScreen extends StatefulWidget {
|
|||
|
||||
class _GameDownloadScreenState extends State<GameDownloadScreen> {
|
||||
late Future<List<String>> _future =
|
||||
method.downloadGame("${widget.info.androidLinks[0]}");
|
||||
method.downloadGame(widget.info.androidLinks[0]);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -34,21 +34,19 @@ class _GameDownloadScreenState extends State<GameDownloadScreen> {
|
|||
onRefresh: () async {
|
||||
setState(() {
|
||||
_future =
|
||||
method.downloadGame("${widget.info.androidLinks[0]}");
|
||||
method.downloadGame(widget.info.androidLinks[0]);
|
||||
});
|
||||
},
|
||||
successBuilder:
|
||||
(BuildContext context, AsyncSnapshot<List<String>> snapshot) {
|
||||
return Container(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.all(30),
|
||||
child: Text('获取到下载链接, 您只需要选择其中一个'),
|
||||
),
|
||||
...snapshot.data!.map((e) => _copyCard(e)),
|
||||
],
|
||||
),
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(30),
|
||||
child: const Text('获取到下载链接, 您只需要选择其中一个'),
|
||||
),
|
||||
...snapshot.data!.map((e) => _copyCard(e)),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
@ -14,7 +14,7 @@ import 'components/GameTitleCard.dart';
|
|||
class GameInfoScreen extends StatefulWidget {
|
||||
final String gameId;
|
||||
|
||||
const GameInfoScreen(this.gameId);
|
||||
const GameInfoScreen(this.gameId,{Key? key}):super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _GameInfoScreenState();
|
||||
|
@ -127,33 +127,31 @@ class _GameInfoScreenState extends State<GameInfoScreen> {
|
|||
),
|
||||
),
|
||||
Container(height: 20),
|
||||
Container(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 40,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.025),
|
||||
child: TabBar(
|
||||
tabs: <Widget>[
|
||||
Tab(text: '详情 '),
|
||||
Tab(text: '评论 (${info.commentsCount})'),
|
||||
],
|
||||
indicatorColor:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
labelColor:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
onTap: (val) async {
|
||||
setState(() {
|
||||
_tabIndex = val;
|
||||
});
|
||||
},
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Container(
|
||||
height: 40,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondary
|
||||
.withOpacity(.025),
|
||||
child: TabBar(
|
||||
tabs: <Widget>[
|
||||
Tab(text: '详情 '),
|
||||
Tab(text: '评论 (${info.commentsCount})'),
|
||||
],
|
||||
indicatorColor:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
labelColor:
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
onTap: (val) async {
|
||||
setState(() {
|
||||
_tabIndex = val;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
_tabIndex == 0
|
||||
? Container(
|
||||
|
|
|
@ -9,6 +9,8 @@ import 'components/Images.dart';
|
|||
|
||||
// 游戏列表
|
||||
class GamesScreen extends StatefulWidget {
|
||||
const GamesScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _GamesScreenState();
|
||||
}
|
||||
|
@ -43,7 +45,7 @@ class _GamesScreenState extends State<GamesScreen> {
|
|||
|
||||
List<Wrap> wraps = [];
|
||||
GameCard? gameCard;
|
||||
page.docs.forEach((element) {
|
||||
for (var element in page.docs) {
|
||||
if (gameCard == null) {
|
||||
gameCard = GameCard(element);
|
||||
} else {
|
||||
|
@ -53,7 +55,7 @@ class _GamesScreenState extends State<GamesScreen> {
|
|||
));
|
||||
gameCard = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (gameCard != null) {
|
||||
wraps.add(Wrap(
|
||||
children: [gameCard!],
|
||||
|
@ -85,18 +87,16 @@ class _GamesScreenState extends State<GamesScreen> {
|
|||
builder: (context) {
|
||||
return AlertDialog(
|
||||
content: Card(
|
||||
child: Container(
|
||||
child: TextField(
|
||||
controller: _textEditController,
|
||||
decoration: new InputDecoration(
|
||||
labelText: "请输入页数:",
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.allow(
|
||||
RegExp(r'\d+')),
|
||||
],
|
||||
child: TextField(
|
||||
controller: _textEditController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: "请输入页数:",
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.allow(
|
||||
RegExp(r'\d+')),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
|
@ -104,13 +104,13 @@ class _GamesScreenState extends State<GamesScreen> {
|
|||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text('取消'),
|
||||
child: const Text('取消'),
|
||||
),
|
||||
MaterialButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
var text = _textEditController.text;
|
||||
if (text.length == 0 || text.length > 5) {
|
||||
if (text.isEmpty || text.length > 5) {
|
||||
return;
|
||||
}
|
||||
var num = int.parse(text);
|
||||
|
@ -119,7 +119,7 @@ class _GamesScreenState extends State<GamesScreen> {
|
|||
}
|
||||
_onPageChange(num);
|
||||
},
|
||||
child: Text('确定'),
|
||||
child: const Text('确定'),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
@ -186,7 +186,7 @@ class _GamesScreenState extends State<GamesScreen> {
|
|||
class GameCard extends StatelessWidget {
|
||||
final GameSimple info;
|
||||
|
||||
GameCard(this.info);
|
||||
const GameCard(this.info, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -215,8 +215,8 @@ class GameCard extends StatelessWidget {
|
|||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: SizedBox(
|
||||
width: imageWidth,
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
|
@ -36,6 +36,8 @@ import 'AppScreen.dart';
|
|||
|
||||
// 初始化界面
|
||||
class InitScreen extends StatefulWidget {
|
||||
const InitScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _InitScreenState();
|
||||
}
|
||||
|
@ -104,7 +106,7 @@ class _InitScreenState extends State<InitScreen> {
|
|||
backgroundColor: Color(0xfffffced),
|
||||
body: ConstrainedBox(
|
||||
constraints: BoxConstraints.expand(),
|
||||
child: new Image.asset(
|
||||
child: Image.asset(
|
||||
"lib/assets/init.jpg",
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
|
|
|
@ -8,12 +8,14 @@ import 'package:pikapika/screens/components/ContentLoading.dart';
|
|||
|
||||
// 数据迁移页面
|
||||
class MigrateScreen extends StatefulWidget {
|
||||
const MigrateScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _MigrateScreenState();
|
||||
}
|
||||
|
||||
class _MigrateScreenState extends State<MigrateScreen> {
|
||||
late Future _future = _load();
|
||||
late final Future _future = _load();
|
||||
late String _current;
|
||||
late List<String> paths;
|
||||
String _message = "";
|
||||
|
|
|
@ -89,14 +89,14 @@ class _RegisterScreenState extends State<RegisterScreen> {
|
|||
if (_registerOver) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('注册成功'),
|
||||
title: const Text('注册成功'),
|
||||
),
|
||||
body: Center(
|
||||
child: Container(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(child: Container()),
|
||||
Text('您已经注册成功, 请返回登录'),
|
||||
const Text('您已经注册成功, 请返回登录'),
|
||||
Text('账号 : $_email'),
|
||||
Text('昵称 : $_name'),
|
||||
Expanded(child: Container()),
|
||||
|
|
|
@ -24,9 +24,9 @@ class SearchScreen extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _SearchScreenState extends State<SearchScreen> {
|
||||
late TextEditingController _textEditController =
|
||||
late final TextEditingController _textEditController =
|
||||
TextEditingController(text: widget.keyword);
|
||||
late SearchBar _searchBar = SearchBar(
|
||||
late final SearchBar _searchBar = SearchBar(
|
||||
hintText: '搜索 ${categoryTitle(widget.category)}',
|
||||
controller: _textEditController,
|
||||
inBar: false,
|
||||
|
|
|
@ -34,12 +34,14 @@ import 'MigrateScreen.dart';
|
|||
import 'ModifyPasswordScreen.dart';
|
||||
|
||||
class SettingsScreen extends StatelessWidget {
|
||||
const SettingsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Scaffold(
|
||||
appBar: AppBar(title: Text('设置')),
|
||||
appBar: AppBar(title: const Text('设置')),
|
||||
body: ListView(
|
||||
children: [
|
||||
Divider(),
|
||||
const Divider(),
|
||||
ListTile(
|
||||
onTap: () async {
|
||||
Navigator.push(
|
||||
|
@ -48,11 +50,11 @@ class SettingsScreen extends StatelessWidget {
|
|||
builder: (context) => ModifyPasswordScreen()),
|
||||
);
|
||||
},
|
||||
title: Text('修改密码'),
|
||||
title: const Text('修改密码'),
|
||||
),
|
||||
Divider(),
|
||||
NetworkSetting(),
|
||||
Divider(),
|
||||
const Divider(),
|
||||
const NetworkSetting(),
|
||||
const Divider(),
|
||||
qualitySetting(),
|
||||
convertToPNGSetting(),
|
||||
readerTypeSetting(),
|
||||
|
@ -63,7 +65,7 @@ class SettingsScreen extends StatelessWidget {
|
|||
volumeControllerSetting(),
|
||||
keyboardControllerSetting(),
|
||||
noAnimationSetting(),
|
||||
Divider(),
|
||||
const Divider(),
|
||||
shadowCategoriesModeSetting(),
|
||||
shadowCategoriesSetting(),
|
||||
pagerActionSetting(),
|
||||
|
|
|
@ -15,7 +15,8 @@ import 'components/UserProfileCard.dart';
|
|||
|
||||
// 个人空间页面
|
||||
class SpaceScreen extends StatefulWidget {
|
||||
const SpaceScreen();
|
||||
const SpaceScreen({Key? key}) : super(key: key);
|
||||
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _SpaceScreenState();
|
||||
|
@ -58,17 +59,17 @@ class _SpaceScreenState extends State<SpaceScreen> {
|
|||
);
|
||||
}
|
||||
},
|
||||
icon: Icon(Icons.exit_to_app),
|
||||
icon: const Icon(Icons.exit_to_app),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => AboutScreen()),
|
||||
MaterialPageRoute(builder: (context) => const AboutScreen()),
|
||||
);
|
||||
},
|
||||
icon: Badged(
|
||||
child: Icon(Icons.info_outline),
|
||||
child: const Icon(Icons.info_outline),
|
||||
badge: latestVersion() == null ? null : "1",
|
||||
),
|
||||
),
|
||||
|
@ -76,18 +77,18 @@ class _SpaceScreenState extends State<SpaceScreen> {
|
|||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => SettingsScreen()),
|
||||
MaterialPageRoute(builder: (context) => const SettingsScreen()),
|
||||
);
|
||||
},
|
||||
icon: Icon(Icons.settings),
|
||||
icon: const Icon(Icons.settings),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
Divider(),
|
||||
UserProfileCard(),
|
||||
Divider(),
|
||||
const Divider(),
|
||||
const UserProfileCard(),
|
||||
const Divider(),
|
||||
ListTile(
|
||||
onTap: () async {
|
||||
await chooseTheme(context);
|
||||
|
@ -96,7 +97,7 @@ class _SpaceScreenState extends State<SpaceScreen> {
|
|||
title: Text('主题'),
|
||||
subtitle: Text(currentThemeName()),
|
||||
),
|
||||
Divider(),
|
||||
const Divider(),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
|
@ -106,7 +107,7 @@ class _SpaceScreenState extends State<SpaceScreen> {
|
|||
},
|
||||
title: Text('我的收藏'),
|
||||
),
|
||||
Divider(),
|
||||
const Divider(),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
|
@ -116,17 +117,17 @@ class _SpaceScreenState extends State<SpaceScreen> {
|
|||
},
|
||||
title: Text('浏览记录'),
|
||||
),
|
||||
Divider(),
|
||||
const Divider(),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => DownloadListScreen()),
|
||||
MaterialPageRoute(builder: (context) => const DownloadListScreen()),
|
||||
);
|
||||
},
|
||||
title: Text('我的下载'),
|
||||
title: const Text('我的下载'),
|
||||
),
|
||||
Divider(),
|
||||
const Divider(),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
@ -7,7 +7,7 @@ import 'components/Images.dart';
|
|||
|
||||
// 浏览记录
|
||||
class ViewLogsScreen extends StatefulWidget {
|
||||
const ViewLogsScreen();
|
||||
const ViewLogsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ViewLogsScreenState();
|
||||
|
@ -175,7 +175,7 @@ class ViewLogWrap extends StatelessWidget {
|
|||
onDelete(e.id);
|
||||
},
|
||||
child: Card(
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: width,
|
||||
child: Column(
|
||||
children: [
|
||||
|
@ -200,7 +200,7 @@ class ViewLogWrap extends StatelessWidget {
|
|||
);
|
||||
});
|
||||
|
||||
Map<int, List<Widget>> map = Map();
|
||||
Map<int, List<Widget>> map = {};
|
||||
for (var i = 0; i < entries.length; i++) {
|
||||
late List<Widget> list;
|
||||
if (i % 4 == 0) {
|
||||
|
|
|
@ -10,7 +10,7 @@ class Avatar extends StatelessWidget {
|
|||
final RemoteImageInfo avatarImage;
|
||||
final double size;
|
||||
|
||||
const Avatar(this.avatarImage, {this.size = 50});
|
||||
const Avatar(this.avatarImage, {this.size = 50, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -15,21 +15,21 @@ class Badged extends StatelessWidget {
|
|||
return Stack(
|
||||
children: [
|
||||
child,
|
||||
new Positioned(
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: new Container(
|
||||
padding: EdgeInsets.all(1),
|
||||
decoration: new BoxDecoration(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(1),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
constraints: BoxConstraints(
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 12,
|
||||
minHeight: 12,
|
||||
),
|
||||
child: new Text(
|
||||
child: Text(
|
||||
badge!,
|
||||
style: new TextStyle(
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 8,
|
||||
),
|
||||
|
|
|
@ -4,13 +4,14 @@ import 'package:flutter/material.dart';
|
|||
class ComicDescriptionCard extends StatelessWidget {
|
||||
final String description;
|
||||
|
||||
ComicDescriptionCard({Key? key, required this.description}) : super(key: key);
|
||||
const ComicDescriptionCard({Key? key, required this.description})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
return Container(
|
||||
padding: EdgeInsets.only(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5,
|
||||
bottom: 5,
|
||||
left: 10,
|
||||
|
|
|
@ -168,7 +168,7 @@ class _ComicInfoCard extends State<ComicInfoCard> {
|
|||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: imageHeight,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
|
@ -180,7 +180,7 @@ class _ComicInfoCard extends State<ComicInfoCard> {
|
|||
? []
|
||||
: [
|
||||
Container(height: 10),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: 26,
|
||||
child: _likeLoading
|
||||
? IconButton(
|
||||
|
@ -205,7 +205,7 @@ class _ComicInfoCard extends State<ComicInfoCard> {
|
|||
? []
|
||||
: [
|
||||
Container(height: 10),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: 26,
|
||||
child: _favouriteLoading
|
||||
? IconButton(
|
||||
|
|
|
@ -18,7 +18,9 @@ class ComicList extends StatefulWidget {
|
|||
final List<ComicSimple> comicList;
|
||||
final ScrollController? controller;
|
||||
|
||||
const ComicList(this.comicList, {this.appendWidget, this.controller});
|
||||
const ComicList(this.comicList,
|
||||
{this.appendWidget, this.controller, Key? key})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ComicListState();
|
||||
|
@ -112,7 +114,7 @@ class _ComicListState extends State<ComicList> {
|
|||
}).toList(),
|
||||
...widget.appendWidget != null
|
||||
? [
|
||||
Container(
|
||||
SizedBox(
|
||||
height: 80,
|
||||
child: widget.appendWidget,
|
||||
),
|
||||
|
@ -132,7 +134,7 @@ class _ComicListState extends State<ComicList> {
|
|||
var height = width * coverHeight / coverWidth;
|
||||
List<Widget> wraps = [];
|
||||
List<Widget> tmp = [];
|
||||
widget.comicList.forEach((e) {
|
||||
for (var e in widget.comicList) {
|
||||
var shadow = e.categories.map(
|
||||
(c) {
|
||||
switch (currentShadowCategoriesMode()) {
|
||||
|
@ -193,12 +195,13 @@ class _ComicListState extends State<ComicList> {
|
|||
));
|
||||
tmp = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
// 追加特殊按钮
|
||||
if (widget.appendWidget != null) {
|
||||
tmp.add(Container(
|
||||
color: (Theme.of(context).textTheme.bodyText1?.color ?? Color(0))
|
||||
.withOpacity(.1),
|
||||
color:
|
||||
(Theme.of(context).textTheme.bodyText1?.color ?? Colors.transparent)
|
||||
.withOpacity(.1),
|
||||
margin: EdgeInsets.only(
|
||||
left: (rowCap - tmp.length) * gap,
|
||||
right: (rowCap - tmp.length) * gap,
|
||||
|
@ -211,7 +214,7 @@ class _ComicListState extends State<ComicList> {
|
|||
));
|
||||
}
|
||||
// 最后一页没有下一页所有有可能为空
|
||||
if (tmp.length > 0) {
|
||||
if (tmp.isNotEmpty) {
|
||||
wraps.add(Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
|
@ -240,7 +243,7 @@ class _ComicListState extends State<ComicList> {
|
|||
double shadowFontSize = max(width / 9, 12);
|
||||
List<Widget> wraps = [];
|
||||
List<Widget> tmp = [];
|
||||
widget.comicList.forEach((e) {
|
||||
for (var e in widget.comicList) {
|
||||
var shadow = e.categories.map(
|
||||
(c) {
|
||||
switch (currentShadowCategoriesMode()) {
|
||||
|
@ -330,12 +333,13 @@ class _ComicListState extends State<ComicList> {
|
|||
));
|
||||
tmp = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
// 追加特殊按钮
|
||||
if (widget.appendWidget != null) {
|
||||
tmp.add(Container(
|
||||
color: (Theme.of(context).textTheme.bodyText1?.color ?? Color(0))
|
||||
.withOpacity(.1),
|
||||
color:
|
||||
(Theme.of(context).textTheme.bodyText1?.color ?? Colors.transparent)
|
||||
.withOpacity(.1),
|
||||
margin: EdgeInsets.only(
|
||||
left: (rowCap - tmp.length) * gap,
|
||||
right: (rowCap - tmp.length) * gap,
|
||||
|
@ -348,7 +352,7 @@ class _ComicListState extends State<ComicList> {
|
|||
));
|
||||
}
|
||||
// 最后一页没有下一页所有有可能为空
|
||||
if (tmp.length > 0) {
|
||||
if (tmp.isNotEmpty) {
|
||||
wraps.add(Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
|
|
|
@ -10,7 +10,8 @@ class ComicListBuilder extends StatefulWidget {
|
|||
final Future<List<ComicSimple>> future;
|
||||
final Future Function() reload;
|
||||
|
||||
ComicListBuilder(this.future, this.reload);
|
||||
const ComicListBuilder(this.future, this.reload, {Key? key})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ComicListBuilderState();
|
||||
|
|
|
@ -153,17 +153,15 @@ class _ControllerComicPagerState extends State<ControllerComicPager> {
|
|||
builder: (context) {
|
||||
return AlertDialog(
|
||||
content: Card(
|
||||
child: Container(
|
||||
child: TextField(
|
||||
controller: _textEditController,
|
||||
decoration: new InputDecoration(
|
||||
labelText: "请输入页数:",
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.allow(RegExp(r'\d+')),
|
||||
],
|
||||
child: TextField(
|
||||
controller: _textEditController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: "请输入页数:",
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: <TextInputFormatter>[
|
||||
FilteringTextInputFormatter.allow(RegExp(r'\d+')),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
|
@ -177,7 +175,7 @@ class _ControllerComicPagerState extends State<ControllerComicPager> {
|
|||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
var text = _textEditController.text;
|
||||
if (text.length == 0 || text.length > 5) {
|
||||
if (text.isEmpty || text.length > 5) {
|
||||
return;
|
||||
}
|
||||
var num = int.parse(text);
|
||||
|
@ -240,6 +238,7 @@ class _ControllerComicPagerState extends State<ControllerComicPager> {
|
|||
text: '下一页',
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,5 +390,6 @@ class _StreamComicPagerState extends State<StreamComicPager> {
|
|||
if (_loading) {
|
||||
return FitButton(onPressed: () {}, text: '加载中');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ class ComicCommentItem extends StatefulWidget {
|
|||
final String mainId;
|
||||
final CommentBase comment;
|
||||
|
||||
const ComicCommentItem(this.mainType, this.mainId, this.comment);
|
||||
const ComicCommentItem(this.mainType, this.mainId, this.comment, {Key? key})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ComicCommentItemState();
|
||||
|
@ -24,7 +25,7 @@ class _ComicCommentItemState extends State<ComicCommentItem> {
|
|||
Widget build(BuildContext context) {
|
||||
var comment = widget.comment;
|
||||
var theme = Theme.of(context);
|
||||
var nameStyle = TextStyle(fontWeight: FontWeight.bold);
|
||||
var nameStyle = const TextStyle(fontWeight: FontWeight.bold);
|
||||
var levelStyle = TextStyle(
|
||||
fontSize: 12, color: theme.colorScheme.secondary.withOpacity(.8));
|
||||
var connectStyle =
|
||||
|
@ -32,7 +33,7 @@ class _ComicCommentItemState extends State<ComicCommentItem> {
|
|||
var datetimeStyle = TextStyle(
|
||||
color: theme.textTheme.bodyText1?.color?.withOpacity(.6), fontSize: 12);
|
||||
return Container(
|
||||
padding: EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
|
@ -58,7 +59,7 @@ class _ComicCommentItemState extends State<ComicCommentItem> {
|
|||
children: [
|
||||
LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Container(
|
||||
return SizedBox(
|
||||
width: constraints.maxWidth,
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
|
@ -77,7 +78,7 @@ class _ComicCommentItemState extends State<ComicCommentItem> {
|
|||
Container(height: 3),
|
||||
LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Container(
|
||||
return SizedBox(
|
||||
width: constraints.maxWidth,
|
||||
child: Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
|
@ -103,7 +104,7 @@ class _ComicCommentItemState extends State<ComicCommentItem> {
|
|||
text: '${comment.commentsCount}',
|
||||
),
|
||||
])
|
||||
: TextSpan(),
|
||||
: const TextSpan(),
|
||||
WidgetSpan(child: Container(width: 12)),
|
||||
WidgetSpan(
|
||||
child: GestureDetector(
|
||||
|
@ -136,6 +137,7 @@ class _ComicCommentItemState extends State<ComicCommentItem> {
|
|||
}
|
||||
});
|
||||
} catch (e, s) {
|
||||
print("$e\n$s");
|
||||
defaultToast(context, "点赞失败");
|
||||
} finally {
|
||||
setState(() {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:pikapika/basic/config/ContentFailedReloadAction.dart';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:pikapika/basic/enum/ErrorTypes.dart';
|
||||
|
||||
|
@ -60,21 +59,19 @@ class ContentError extends StatelessWidget {
|
|||
onTap: onRefresh,
|
||||
child: ListView(
|
||||
children: [
|
||||
Container(
|
||||
SizedBox(
|
||||
height: height,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(child: Container()),
|
||||
Container(
|
||||
child: Icon(
|
||||
iconData,
|
||||
size: iconSize,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
Icon(
|
||||
iconData,
|
||||
size: iconSize,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
Container(height: min / 10),
|
||||
Container(
|
||||
padding: EdgeInsets.only(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 30,
|
||||
right: 30,
|
||||
),
|
||||
|
@ -99,21 +96,19 @@ class ContentError extends StatelessWidget {
|
|||
onRefresh: onRefresh,
|
||||
child: ListView(
|
||||
children: [
|
||||
Container(
|
||||
SizedBox(
|
||||
height: height,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(child: Container()),
|
||||
Container(
|
||||
child: Icon(
|
||||
iconData,
|
||||
size: iconSize,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
Icon(
|
||||
iconData,
|
||||
size: iconSize,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
Container(height: min / 10),
|
||||
Container(
|
||||
padding: EdgeInsets.only(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 30,
|
||||
right: 30,
|
||||
),
|
||||
|
|
|
@ -115,53 +115,43 @@ class DownloadInfoCard extends StatelessWidget {
|
|||
),
|
||||
Container(width: 20),
|
||||
task.deleting
|
||||
? Container(
|
||||
child: Text('删除中',
|
||||
? Text('删除中',
|
||||
style: TextStyle(
|
||||
color: Color.alphaBlend(
|
||||
textColor.withAlpha(0x33),
|
||||
Colors.red.shade500)))
|
||||
: task.downloadFailed
|
||||
? Text('下载失败',
|
||||
style: TextStyle(
|
||||
color: Color.alphaBlend(
|
||||
textColor.withAlpha(0x33),
|
||||
Colors.red.shade500))),
|
||||
)
|
||||
: task.downloadFailed
|
||||
? Container(
|
||||
child: Text('下载失败',
|
||||
Colors.red.shade500)))
|
||||
: task.downloadFinished
|
||||
? Text('下载完成',
|
||||
style: TextStyle(
|
||||
color: Color.alphaBlend(
|
||||
textColor.withAlpha(0x33),
|
||||
Colors.red.shade500))),
|
||||
)
|
||||
: task.downloadFinished
|
||||
? Container(
|
||||
child: Text('下载完成',
|
||||
textColorAlpha,
|
||||
Colors.green.shade500)))
|
||||
: downloading // downloader.downloadingTask() == task.id
|
||||
? Text('下载中',
|
||||
style: TextStyle(
|
||||
color: Color.alphaBlend(
|
||||
textColorAlpha,
|
||||
Colors.green.shade500))),
|
||||
)
|
||||
: downloading // downloader.downloadingTask() == task.id
|
||||
? Container(
|
||||
child: Text('下载中',
|
||||
style: TextStyle(
|
||||
color: Color.alphaBlend(
|
||||
textColorAlpha,
|
||||
Colors
|
||||
.blue.shade500))),
|
||||
)
|
||||
: Container(
|
||||
child: Text('队列中',
|
||||
style: TextStyle(
|
||||
color: Color.alphaBlend(
|
||||
textColorAlpha,
|
||||
Colors.lightBlue
|
||||
.shade500))),
|
||||
),
|
||||
Colors
|
||||
.blue.shade500)))
|
||||
: Text('队列中',
|
||||
style: TextStyle(
|
||||
color: Color.alphaBlend(
|
||||
textColorAlpha,
|
||||
Colors.lightBlue
|
||||
.shade500))),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
padding: const EdgeInsets.only(left: 8),
|
||||
height: imageHeight,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
|
|
|
@ -15,13 +15,11 @@ class FitButton extends StatelessWidget {
|
|||
width: constraints.maxWidth,
|
||||
height: constraints.maxHeight,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: MaterialButton(
|
||||
onPressed: onPressed,
|
||||
child: Container(
|
||||
child: Center(
|
||||
child: Text(text),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(text),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -9,21 +9,20 @@ import 'Images.dart';
|
|||
class GameTitleCard extends StatelessWidget {
|
||||
final GameInfo info;
|
||||
|
||||
const GameTitleCard(this.info);
|
||||
const GameTitleCard(this.info, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double iconMargin = 20;
|
||||
double iconSize = 60;
|
||||
BorderRadius iconRadius = BorderRadius.all(Radius.circular(6));
|
||||
TextStyle titleStyle = TextStyle(fontSize: 16, fontWeight: FontWeight.bold);
|
||||
BorderRadius iconRadius = const BorderRadius.all(Radius.circular(6));
|
||||
TextStyle titleStyle =
|
||||
const TextStyle(fontSize: 16, fontWeight: FontWeight.bold);
|
||||
TextStyle publisherStyle = TextStyle(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
fontSize: 12.5,
|
||||
);
|
||||
TextStyle versionStyle = TextStyle(
|
||||
fontSize: 12.5,
|
||||
);
|
||||
TextStyle versionStyle = const TextStyle(fontSize: 12.5);
|
||||
double platformMargin = 10;
|
||||
double platformSize = 25;
|
||||
return Row(
|
||||
|
|
|
@ -139,7 +139,7 @@ class ImageReaderStruct {
|
|||
class ImageReader extends StatefulWidget {
|
||||
final ImageReaderStruct struct;
|
||||
|
||||
const ImageReader(this.struct);
|
||||
const ImageReader(this.struct, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ImageReaderState();
|
||||
|
@ -153,9 +153,9 @@ class _ImageReaderState extends State<ImageReader> {
|
|||
final ReaderType _pagerType = currentReaderType();
|
||||
|
||||
// 记录了控制器
|
||||
late FullScreenAction _fullScreenAction = currentFullScreenAction();
|
||||
late final FullScreenAction _fullScreenAction = currentFullScreenAction();
|
||||
|
||||
late ReaderSliderPosition _readerSliderPosition =
|
||||
late final ReaderSliderPosition _readerSliderPosition =
|
||||
currentReaderSliderPosition();
|
||||
|
||||
@override
|
||||
|
@ -245,7 +245,7 @@ abstract class _ImageReaderContentState extends State<_ImageReaderContent> {
|
|||
void _onPageControl(_ReaderControllerEventArgs? args) {
|
||||
if (args != null) {
|
||||
var event = args.key;
|
||||
switch ("$event") {
|
||||
switch (event) {
|
||||
case "UP":
|
||||
if (_current > 0) {
|
||||
_needJumpTo(_current - 1, true);
|
||||
|
@ -369,7 +369,6 @@ abstract class _ImageReaderContentState extends State<_ImageReaderContent> {
|
|||
],
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
}
|
||||
|
||||
Widget _buildAppBar() => widget.struct.fullScreen
|
||||
|
@ -393,7 +392,7 @@ abstract class _ImageReaderContentState extends State<_ImageReaderContent> {
|
|||
return Column(
|
||||
children: [
|
||||
Expanded(child: Container()),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: 25,
|
||||
child: _buildSliderWidget(Axis.horizontal),
|
||||
),
|
||||
|
@ -407,7 +406,7 @@ abstract class _ImageReaderContentState extends State<_ImageReaderContent> {
|
|||
: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Material(
|
||||
color: Color(0x0),
|
||||
color: Colors.transparent,
|
||||
child: Container(
|
||||
width: 35,
|
||||
height: 300,
|
||||
|
@ -431,7 +430,7 @@ abstract class _ImageReaderContentState extends State<_ImageReaderContent> {
|
|||
: Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Material(
|
||||
color: Color(0x0),
|
||||
color: Colors.transparent,
|
||||
child: Container(
|
||||
width: 35,
|
||||
height: 300,
|
||||
|
@ -525,7 +524,7 @@ abstract class _ImageReaderContentState extends State<_ImageReaderContent> {
|
|||
return Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Material(
|
||||
color: Color(0x0),
|
||||
color: Colors.transparent,
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4),
|
||||
margin: EdgeInsets.only(bottom: 10),
|
||||
|
@ -577,8 +576,7 @@ abstract class _ImageReaderContentState extends State<_ImageReaderContent> {
|
|||
return GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () {
|
||||
_readerControllerEvent
|
||||
.broadcast(_ReaderControllerEventArgs("DOWN"));
|
||||
_readerControllerEvent.broadcast(_ReaderControllerEventArgs("DOWN"));
|
||||
},
|
||||
onDoubleTap: () {
|
||||
widget.struct.onFullScreenChange(!widget.struct.fullScreen);
|
||||
|
@ -656,7 +654,7 @@ abstract class _ImageReaderContentState extends State<_ImageReaderContent> {
|
|||
context: context,
|
||||
backgroundColor: Color(0xAA000000),
|
||||
builder: (context) {
|
||||
return Container(
|
||||
return SizedBox(
|
||||
height: MediaQuery.of(context).size.height * (.45),
|
||||
child: _EpChooser(
|
||||
widget.struct.epNameMap,
|
||||
|
@ -677,7 +675,7 @@ abstract class _ImageReaderContentState extends State<_ImageReaderContent> {
|
|||
context: context,
|
||||
backgroundColor: Color(0xAA000000),
|
||||
builder: (context) {
|
||||
return Container(
|
||||
return SizedBox(
|
||||
height: MediaQuery.of(context).size.height * (.45),
|
||||
child: _SettingPanel(
|
||||
widget.struct.onReloadEp,
|
||||
|
@ -749,11 +747,11 @@ class _EpChooserState extends State<_EpChooser> {
|
|||
Container(height: 20),
|
||||
...entries.map((e) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
|
||||
margin: const EdgeInsets.only(left: 15, right: 15, top: 5, bottom: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: widget.epOrder == e.key ? Colors.grey.withAlpha(100) : null,
|
||||
border: Border.all(
|
||||
color: Color(0xff484c60),
|
||||
color: const Color(0xff484c60),
|
||||
style: BorderStyle.solid,
|
||||
width: .5,
|
||||
),
|
||||
|
@ -764,7 +762,7 @@ class _EpChooserState extends State<_EpChooser> {
|
|||
widget.onChangeEp(e.key);
|
||||
},
|
||||
textColor: Colors.white,
|
||||
child: Text('${e.value}'),
|
||||
child: Text(e.value),
|
||||
),
|
||||
);
|
||||
})
|
||||
|
@ -792,78 +790,74 @@ class _SettingPanelState extends State<_SettingPanel> {
|
|||
Widget build(BuildContext context) {
|
||||
return ListView(
|
||||
children: [
|
||||
Container(
|
||||
child: Row(
|
||||
children: [
|
||||
_bottomIcon(
|
||||
icon: Icons.crop_sharp,
|
||||
title: gReaderDirectionName(),
|
||||
onPressed: () async {
|
||||
await choosePagerDirection(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.view_day_outlined,
|
||||
title: currentReaderTypeName(),
|
||||
onPressed: () async {
|
||||
await choosePagerType(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.image_aspect_ratio_outlined,
|
||||
title: currentQualityName(),
|
||||
onPressed: () async {
|
||||
await chooseQuality(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.control_camera_outlined,
|
||||
title: currentFullScreenActionName(),
|
||||
onPressed: () async {
|
||||
await chooseFullScreenAction(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
_bottomIcon(
|
||||
icon: Icons.crop_sharp,
|
||||
title: gReaderDirectionName(),
|
||||
onPressed: () async {
|
||||
await choosePagerDirection(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.view_day_outlined,
|
||||
title: currentReaderTypeName(),
|
||||
onPressed: () async {
|
||||
await choosePagerType(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.image_aspect_ratio_outlined,
|
||||
title: currentQualityName(),
|
||||
onPressed: () async {
|
||||
await chooseQuality(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.control_camera_outlined,
|
||||
title: currentFullScreenActionName(),
|
||||
onPressed: () async {
|
||||
await chooseFullScreenAction(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
child: Row(
|
||||
children: [
|
||||
_bottomIcon(
|
||||
icon: Icons.shuffle,
|
||||
title: currentAddressName(),
|
||||
onPressed: () async {
|
||||
await chooseAddress(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.repeat_one,
|
||||
title: currentImageAddressName(),
|
||||
onPressed: () async {
|
||||
await chooseImageAddress(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.refresh,
|
||||
title: "重载页面",
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
widget.onReloadEp();
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.file_download,
|
||||
title: "下载本作",
|
||||
onPressed: widget.onDownload,
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
_bottomIcon(
|
||||
icon: Icons.shuffle,
|
||||
title: currentAddressName(),
|
||||
onPressed: () async {
|
||||
await chooseAddress(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.repeat_one,
|
||||
title: currentImageAddressName(),
|
||||
onPressed: () async {
|
||||
await chooseImageAddress(context);
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.refresh,
|
||||
title: "重载页面",
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
widget.onReloadEp();
|
||||
},
|
||||
),
|
||||
_bottomIcon(
|
||||
icon: Icons.file_download,
|
||||
title: "下载本作",
|
||||
onPressed: widget.onDownload,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
@ -917,13 +911,13 @@ class _WebToonReaderState extends _ImageReaderContentState {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
widget.struct.images.forEach((e) {
|
||||
for (var e in widget.struct.images) {
|
||||
if (e.downloadLocalPath != null) {
|
||||
_trueSizes.add(Size(e.width!.toDouble(), e.height!.toDouble()));
|
||||
} else {
|
||||
_trueSizes.add(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
_itemScrollController = ItemScrollController();
|
||||
_itemPositionsListener = ItemPositionsListener.create();
|
||||
_itemPositionsListener.itemPositions.addListener(_onListCurrentChange);
|
||||
|
@ -1077,7 +1071,7 @@ class _WebToonReaderState extends _ImageReaderContentState {
|
|||
}
|
||||
return Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.all(20),
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: MaterialButton(
|
||||
onPressed: () {
|
||||
if (super._hasNextEp()) {
|
||||
|
@ -1238,18 +1232,18 @@ class _ListViewReaderState extends _ImageReaderContentState
|
|||
late TapDownDetails _doubleTapDetails;
|
||||
late final _animationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: Duration(milliseconds: 100),
|
||||
duration: const Duration(milliseconds: 100),
|
||||
);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
widget.struct.images.forEach((e) {
|
||||
for (var e in widget.struct.images) {
|
||||
if (e.downloadLocalPath != null) {
|
||||
_trueSizes.add(Size(e.width!.toDouble(), e.height!.toDouble()));
|
||||
} else {
|
||||
_trueSizes.add(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -1467,6 +1461,7 @@ class _GalleryReaderState extends _ImageReaderContentState {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget _buildViewer() {
|
||||
Widget gallery = PhotoViewGallery.builder(
|
||||
scrollDirection: widget.pagerDirection == ReaderDirection.TOP_TO_BOTTOM
|
||||
|
@ -1574,7 +1569,7 @@ class _GalleryReaderState extends _ImageReaderContentState {
|
|||
return Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Material(
|
||||
color: Color(0x0),
|
||||
color: Colors.transparent,
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(bottom: 10),
|
||||
padding: EdgeInsets.only(left: 10, right: 10, top: 4, bottom: 4),
|
||||
|
|
|
@ -181,7 +181,7 @@ class DownloadImage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _DownloadImageState extends State<DownloadImage> {
|
||||
late Future<String> _future = method.downloadImagePath(widget.path);
|
||||
late final Future<String> _future = method.downloadImagePath(widget.path);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -276,7 +276,7 @@ Widget buildSvg(String source, double? width, double? height,
|
|||
var widget = Container(
|
||||
width: width,
|
||||
height: height,
|
||||
padding: margin != null ? EdgeInsets.all(10) : null,
|
||||
padding: margin != null ? const EdgeInsets.all(10) : null,
|
||||
child: Center(
|
||||
child: SvgPicture.asset(
|
||||
source,
|
||||
|
@ -319,7 +319,7 @@ Widget buildLoading(double? width, double? height) {
|
|||
if (width != null && height != null) {
|
||||
size = width < height ? width : height;
|
||||
}
|
||||
return Container(
|
||||
return SizedBox(
|
||||
width: width,
|
||||
height: height,
|
||||
child: Center(
|
||||
|
|
|
@ -31,7 +31,7 @@ class ItemBuilder<T> extends StatelessWidget {
|
|||
print("${snapshot.stackTrace}");
|
||||
return InkWell(
|
||||
onTap: onRefresh,
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: _maxWidth,
|
||||
height: _loadingHeight,
|
||||
child: Center(
|
||||
|
@ -42,7 +42,7 @@ class ItemBuilder<T> extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return Container(
|
||||
return SizedBox(
|
||||
width: _maxWidth,
|
||||
height: _loadingHeight,
|
||||
child: Center(
|
||||
|
@ -50,7 +50,7 @@ class ItemBuilder<T> extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
return Container(
|
||||
return SizedBox(
|
||||
width: _maxWidth,
|
||||
height: height,
|
||||
child: successBuilder(context, snapshot),
|
||||
|
|
|
@ -10,7 +10,8 @@ class LinkToComicInfo extends StatelessWidget {
|
|||
const LinkToComicInfo({
|
||||
required this.comicId,
|
||||
required this.child,
|
||||
});
|
||||
Key? key,
|
||||
}):super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => InkWell(
|
||||
|
|
|
@ -5,16 +5,16 @@ import 'package:pikapika/basic/config/Proxy.dart';
|
|||
|
||||
// 网络设置
|
||||
class NetworkSetting extends StatelessWidget {
|
||||
const NetworkSetting({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: Column(
|
||||
children: [
|
||||
switchAddressSetting(),
|
||||
imageSwitchAddressSetting(),
|
||||
proxySetting(),
|
||||
],
|
||||
),
|
||||
return Column(
|
||||
children: [
|
||||
switchAddressSetting(),
|
||||
imageSwitchAddressSetting(),
|
||||
proxySetting(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ class _RecommendationState extends State<Recommendation> {
|
|||
(route) => i++ < 10);
|
||||
},
|
||||
child: Card(
|
||||
child: Container(
|
||||
child: SizedBox(
|
||||
width: width,
|
||||
child: Column(
|
||||
children: [
|
||||
|
@ -60,8 +60,8 @@ class _RecommendationState extends State<Recommendation> {
|
|||
e.title + '\n',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(height: 1.4),
|
||||
strutStyle: StrutStyle(height: 1.4),
|
||||
style: const TextStyle(height: 1.4),
|
||||
strutStyle: const StrutStyle(height: 1.4),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -16,6 +16,8 @@ const double _cardHeight = 180;
|
|||
|
||||
// 用户信息卡
|
||||
class UserProfileCard extends StatefulWidget {
|
||||
const UserProfileCard({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _UserProfileCardState();
|
||||
}
|
||||
|
@ -46,11 +48,11 @@ class _UserProfileCardState extends State<UserProfileCard> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
var nameStyle = TextStyle(
|
||||
var nameStyle = const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
var nameStrutStyle = StrutStyle(
|
||||
var nameStrutStyle = const StrutStyle(
|
||||
fontSize: 14,
|
||||
forceStrutHeight: true,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
@ -60,7 +62,7 @@ class _UserProfileCardState extends State<UserProfileCard> {
|
|||
color: theme.colorScheme.secondary.withOpacity(.9),
|
||||
fontWeight: FontWeight.bold,
|
||||
);
|
||||
var levelStrutStyle = StrutStyle(
|
||||
var levelStrutStyle = const StrutStyle(
|
||||
fontSize: 12,
|
||||
forceStrutHeight: true,
|
||||
fontWeight: FontWeight.bold,
|
||||
|
@ -69,7 +71,7 @@ class _UserProfileCardState extends State<UserProfileCard> {
|
|||
fontSize: 10,
|
||||
color: theme.textTheme.bodyText1?.color?.withOpacity(.5),
|
||||
);
|
||||
var sloganStrutStyle = StrutStyle(
|
||||
var sloganStrutStyle = const StrutStyle(
|
||||
fontSize: 10,
|
||||
forceStrutHeight: true,
|
||||
);
|
||||
|
@ -84,34 +86,32 @@ class _UserProfileCardState extends State<UserProfileCard> {
|
|||
UserProfile profile = snapshot.data!;
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
child: Stack(
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: .25, //
|
||||
child: LayoutBuilder(
|
||||
builder:
|
||||
(BuildContext context, BoxConstraints constraints) {
|
||||
return RemoteImage(
|
||||
path: profile.avatar.path,
|
||||
fileServer: profile.avatar.fileServer,
|
||||
width: constraints.maxWidth,
|
||||
height: _cardHeight,
|
||||
);
|
||||
},
|
||||
),
|
||||
Stack(
|
||||
children: [
|
||||
Opacity(
|
||||
opacity: .25, //
|
||||
child: LayoutBuilder(
|
||||
builder:
|
||||
(BuildContext context, BoxConstraints constraints) {
|
||||
return RemoteImage(
|
||||
path: profile.avatar.path,
|
||||
fileServer: profile.avatar.fileServer,
|
||||
width: constraints.maxWidth,
|
||||
height: _cardHeight,
|
||||
);
|
||||
},
|
||||
),
|
||||
Positioned.fromRect(
|
||||
rect: Rect.largest,
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 30, sigmaY: 30),
|
||||
child: Container(),
|
||||
),
|
||||
),
|
||||
Positioned.fromRect(
|
||||
rect: Rect.largest,
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 30, sigmaY: 30),
|
||||
child: Container(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Container(
|
||||
SizedBox(
|
||||
height: _cardHeight,
|
||||
child: Column(
|
||||
children: [
|
||||
|
@ -177,7 +177,7 @@ class _UserProfileCardState extends State<UserProfileCard> {
|
|||
aspectRatioPresets: [
|
||||
CropAspectRatioPreset.square,
|
||||
],
|
||||
aspectRatio: CropAspectRatio(ratioX: 200, ratioY: 200),
|
||||
aspectRatio: const CropAspectRatio(ratioX: 200, ratioY: 200),
|
||||
maxWidth: 200,
|
||||
maxHeight: 200,
|
||||
androidUiSettings: AndroidUiSettings(
|
||||
|
@ -187,7 +187,7 @@ class _UserProfileCardState extends State<UserProfileCard> {
|
|||
initAspectRatio: CropAspectRatioPreset.original,
|
||||
lockAspectRatio: true,
|
||||
),
|
||||
iosUiSettings: IOSUiSettings(
|
||||
iosUiSettings: const IOSUiSettings(
|
||||
resetAspectRatioEnabled: true,
|
||||
aspectRatioLockEnabled: true,
|
||||
title: "修改头像",
|
||||
|
|
|
@ -36,7 +36,7 @@ class _GestureZoomBoxState extends State<GestureZoomBox>
|
|||
bool _isScaling = false;
|
||||
bool _isDragging = false;
|
||||
|
||||
double _maxDragOver = 100; // 拖动超出边界的最大值
|
||||
final double _maxDragOver = 100; // 拖动超出边界的最大值
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
22
pubspec.lock
22
pubspec.lock
|
@ -104,6 +104,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
flutter_localizations:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -174,7 +181,7 @@ packages:
|
|||
name: image_picker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.8.4+9"
|
||||
version: "0.8.4+11"
|
||||
image_picker_for_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -210,6 +217,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.3"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -237,14 +251,14 @@ packages:
|
|||
name: modal_bottom_sheet
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.0.1"
|
||||
multi_select_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: multi_select_flutter
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "4.1.2"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -417,7 +431,7 @@ packages:
|
|||
name: url_launcher_web
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
version: "2.0.9"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -49,6 +49,7 @@ dependencies:
|
|||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^1.0.0
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
|
|
@ -13,7 +13,7 @@ import 'package:pikapika/main.dart';
|
|||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(PikapikaApp());
|
||||
await tester.pumpWidget(const PikapikaApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
|
|
Loading…
Reference in New Issue