mod: 样式、dio异常处理

This commit is contained in:
guozhigq
2023-05-09 14:39:52 +08:00
parent f3b57bfe7b
commit 04668b3591
29 changed files with 469 additions and 342 deletions

View File

@ -15,7 +15,7 @@ class HomeController extends GetxController {
@override
void onInit() {
super.onInit();
queryRcmdFeed('init');
// queryRcmdFeed('init');
}
// 获取推荐
@ -35,6 +35,7 @@ class HomeController extends GetxController {
_currentPage += 1;
}
isLoadingMore = false;
return res;
}
// 下拉刷新

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pilipala/common/skeleton/video_card_v.dart';
import 'package:pilipala/common/widgets/http_error.dart';
import 'package:pilipala/common/widgets/video_card_v.dart';
import './controller.dart';
import 'package:pilipala/common/constants.dart';
@ -16,6 +17,7 @@ class HomePage extends StatefulWidget {
class _HomePageState extends State<HomePage>
with AutomaticKeepAliveClientMixin {
final HomeController _homeController = Get.put(HomeController());
Future? _futureBuilderFuture;
List videoList = [];
@override
@ -24,6 +26,7 @@ class _HomePageState extends State<HomePage>
@override
void initState() {
super.initState();
_futureBuilderFuture = _homeController.queryRcmdFeed('init');
_homeController.videoList.listen((value) {
videoList = value;
setState(() {});
@ -69,26 +72,25 @@ class _HomePageState extends State<HomePage>
? EdgeInsets.zero
: const EdgeInsets.fromLTRB(
StyleString.cardSpace, 0, StyleString.cardSpace, 8),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// 行间距
mainAxisSpacing: StyleString.cardSpace,
// 列间距
crossAxisSpacing: StyleString.cardSpace,
// 列数
crossAxisCount: _homeController.crossAxisCount,
mainAxisExtent: MediaQuery.of(context).size.width /
_homeController.crossAxisCount /
StyleString.aspectRatio +
70),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return videoList.isNotEmpty
? VideoCardV(videoItem: videoList[index])
: const VideoCardVSkeleton();
},
childCount: videoList.isNotEmpty ? videoList.length : 10,
),
sliver: FutureBuilder(
future: _futureBuilderFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map data = snapshot.data as Map;
if (data['status']) {
return Obx(() => contentGrid(
_homeController, _homeController.videoList));
} else {
return HttpError(
errMsg: data['msg'],
fn: () => setState(() {}),
);
}
} else {
// 骨架屏
return contentGrid(_homeController, []);
}
},
),
),
const LoadingMore()
@ -98,6 +100,31 @@ class _HomePageState extends State<HomePage>
// ),
);
}
Widget contentGrid(ctr, videoList) {
return SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// 行间距
mainAxisSpacing: StyleString.cardSpace,
// 列间距
crossAxisSpacing: StyleString.cardSpace,
// 列数
crossAxisCount: ctr.crossAxisCount,
mainAxisExtent: MediaQuery.of(context).size.width /
ctr.crossAxisCount /
StyleString.aspectRatio +
70,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return videoList!.isNotEmpty
? VideoCardV(videoItem: videoList![index])
: const VideoCardVSkeleton();
},
childCount: videoList!.isNotEmpty ? videoList!.length : 10,
),
);
}
}
class MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {

View File

@ -1,4 +1,5 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
@ -10,11 +11,7 @@ class HomeAppBar extends StatelessWidget {
return SliverAppBar(
// forceElevated: true,
scrolledUnderElevation: 0,
toolbarHeight: Platform.isAndroid
? (MediaQuery.of(context).padding.top + 6)
: Platform.isIOS
? MediaQuery.of(context).padding.top - 2
: kToolbarHeight,
toolbarHeight: MediaQuery.of(context).padding.top,
expandedHeight: kToolbarHeight + MediaQuery.of(context).padding.top,
automaticallyImplyLeading: false,
pinned: true,
@ -39,18 +36,12 @@ class HomeAppBar extends StatelessWidget {
actions: [
IconButton(
onPressed: () {},
icon: const FaIcon(
FontAwesomeIcons.magnifyingGlass,
size: 18,
),
),
IconButton(
onPressed: () {},
icon: const FaIcon(
FontAwesomeIcons.envelope,
size: 20,
),
icon: const Icon(CupertinoIcons.search, size: 22),
),
// IconButton(
// onPressed: () {},
// icon: const Icon(CupertinoIcons.bell, size: 22),
// ),
const SizedBox(width: 10)
],
elevation: 0,

View File

@ -24,7 +24,7 @@ class _HotPageState extends State<HotPage> with AutomaticKeepAliveClientMixin {
@override
void initState() {
super.initState();
_futureBuilderFuture = _hotController!.queryHotFeed('init');
_futureBuilderFuture = _hotController.queryHotFeed('init');
_hotController.scrollController.addListener(
() {
if (_hotController.scrollController.position.pixels >=

View File

@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:pilipala/pages/home/view.dart';
@ -12,18 +13,42 @@ class MainController extends GetxController {
];
List navigationBars = [
{
'icon': const Icon(Icons.home_outlined),
'selectedIcon': const Icon(Icons.home),
// 'icon': const Icon(Icons.home_outlined),
// 'selectedIcon': const Icon(Icons.home),
'icon': const Icon(
CupertinoIcons.house,
size: 18,
),
'selectedIcon': const Icon(
CupertinoIcons.house_fill,
size: 18,
),
'label': "推荐",
},
{
'icon': const Icon(Icons.whatshot_outlined),
'selectedIcon': const Icon(Icons.whatshot_rounded),
// 'icon': const Icon(Icons.whatshot_outlined),
// 'selectedIcon': const Icon(Icons.whatshot_rounded),
'icon': const Icon(
CupertinoIcons.flame,
size: 20,
),
'selectedIcon': const Icon(
CupertinoIcons.flame_fill,
size: 20,
),
'label': "热门",
},
{
'icon': const Icon(Icons.person_outline),
'selectedIcon': const Icon(Icons.person),
// 'icon': const Icon(Icons.person_outline),
// 'selectedIcon': const Icon(Icons.person),
'icon': const Icon(
CupertinoIcons.person,
size: 21,
),
'selectedIcon': const Icon(
CupertinoIcons.person_fill,
size: 21,
),
'label': "我的",
}
];

View File

@ -1,7 +1,10 @@
import 'package:get/get.dart';
import 'package:pilipala/http/user.dart';
import 'package:pilipala/models/user/info.dart';
class MineController extends GetxController {
UserInfoData? userInfo;
@override
void onInit() {
super.onInit();

View File

@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
@ -22,13 +23,19 @@ class _MinePageState extends State<MinePage> {
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.light_mode_rounded),
icon: const Icon(
CupertinoIcons.moon,
size: 22,
),
// icon: const Icon(
// CupertinoIcons.sun_max,
// size: 22,
// ),
),
IconButton(
onPressed: () {},
icon: const FaIcon(
FontAwesomeIcons.sliders,
size: 18,
icon: const Icon(
CupertinoIcons.slider_horizontal_3,
),
),
const SizedBox(width: 10),
@ -36,161 +43,183 @@ class _MinePageState extends State<MinePage> {
),
body: RefreshIndicator(
onRefresh: () async {
await Future.delayed(Duration(seconds: 2));
await Future.delayed(const Duration(seconds: 2));
},
child: Column(
children: [
InkWell(
onTap: () {
Get.toNamed(
'/webview',
parameters: {
'url':
'https://passport.bilibili.com/h5-app/passport/login',
'type': 'login',
'pageTitle': '登录bilibili',
},
);
},
child: Padding(
padding: const EdgeInsets.only(top: 10, bottom: 10),
child: Row(
child: LayoutBuilder(
builder: (context, constraint) {
return SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: SizedBox(
height: constraint.maxHeight,
child: Column(
children: [
const SizedBox(width: 20),
ClipOval(
child: Container(
width: 75,
height: 75,
color: Theme.of(context).colorScheme.onInverseSurface,
child: Center(
child: Image.asset('assets/images/loading.png'),
InkWell(
onTap: () {
Get.toNamed(
'/webview',
parameters: {
'url':
'https://passport.bilibili.com/h5-app/passport/login',
'type': 'login',
'pageTitle': '登录bilibili',
},
);
},
child: Padding(
padding: const EdgeInsets.only(top: 10, bottom: 10),
child: Row(
children: [
const SizedBox(width: 20),
ClipOval(
child: Container(
width: 75,
height: 75,
color: Theme.of(context)
.colorScheme
.onInverseSurface,
child: Center(
child:
Image.asset('assets/images/loading.png'),
),
),
),
const SizedBox(width: 14),
Text(
'点击登录',
style: Theme.of(context).textTheme.titleMedium,
),
],
),
),
),
const SizedBox(width: 14),
Text(
'点击登录',
style: Theme.of(context).textTheme.titleMedium,
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(left: 12, right: 12),
child: LayoutBuilder(
builder: (context, constraints) {
TextStyle style = TextStyle(
fontSize: Theme.of(context)
.textTheme
.titleMedium!
.fontSize,
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.bold);
return SizedBox(
height: constraints.maxWidth / 3 * 0.6,
child: GridView.count(
primary: false,
padding: const EdgeInsets.all(0),
crossAxisCount: 3,
childAspectRatio: 1.67,
children: <Widget>[
InkWell(
onTap: () {},
borderRadius: StyleString.mdRadius,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('-', style: style),
const SizedBox(height: 8),
Text(
'动态',
style: Theme.of(context)
.textTheme
.labelMedium,
),
],
),
),
InkWell(
onTap: () {},
borderRadius: StyleString.mdRadius,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'50',
style: style,
),
const SizedBox(height: 8),
Text(
'关注',
style: Theme.of(context)
.textTheme
.labelMedium,
),
],
),
),
InkWell(
onTap: () {},
borderRadius: StyleString.mdRadius,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'-',
style: style,
),
const SizedBox(height: 8),
Text(
'粉丝',
style: Theme.of(context)
.textTheme
.labelMedium,
),
],
),
),
],
),
);
},
),
),
const SizedBox(height: 20),
Padding(
padding: const EdgeInsets.only(left: 12, right: 12),
child: LayoutBuilder(
builder: (context, constraints) {
return SizedBox(
height: constraints.maxWidth / 4 * 0.8,
child: GridView.count(
primary: false,
padding: const EdgeInsets.all(0),
crossAxisCount: 4,
childAspectRatio: 1.25,
children: <Widget>[
ActionItem(
icon:
const Icon(CupertinoIcons.cloud_download),
onTap: () => {},
text: '离线缓存',
),
ActionItem(
icon: const Icon(CupertinoIcons.time),
onTap: () => {},
text: '历史记录',
),
ActionItem(
icon: const Icon(CupertinoIcons.star),
onTap: () => {},
text: '我的收藏',
),
ActionItem(
icon: const Icon(CupertinoIcons.film),
onTap: () => {},
text: '稍后再看',
),
],
),
);
},
),
),
],
),
),
),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(left: 12, right: 12),
child: LayoutBuilder(
builder: (context, constraints) {
TextStyle style = TextStyle(
fontSize:
Theme.of(context).textTheme.titleMedium!.fontSize,
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.bold);
return SizedBox(
height: constraints.maxWidth / 3 * 0.6,
child: GridView.count(
primary: false,
padding: const EdgeInsets.all(0),
crossAxisCount: 3,
childAspectRatio: 1.67,
children: <Widget>[
InkWell(
onTap: () {},
borderRadius: StyleString.mdRadius,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('-', style: style),
const SizedBox(height: 8),
Text(
'动态',
style: Theme.of(context).textTheme.labelMedium,
),
],
),
),
InkWell(
onTap: () {},
borderRadius: StyleString.mdRadius,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'50',
style: style,
),
const SizedBox(height: 8),
Text(
'关注',
style: Theme.of(context).textTheme.labelMedium,
),
],
),
),
InkWell(
onTap: () {},
borderRadius: StyleString.mdRadius,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'-',
style: style,
),
const SizedBox(height: 8),
Text(
'粉丝',
style: Theme.of(context).textTheme.labelMedium,
),
],
),
),
],
),
);
},
),
),
const SizedBox(height: 20),
Padding(
padding: const EdgeInsets.only(left: 12, right: 12),
child: LayoutBuilder(
builder: (context, constraints) {
return SizedBox(
height: constraints.maxWidth / 4 * 0.8,
child: GridView.count(
primary: false,
padding: const EdgeInsets.all(0),
crossAxisCount: 4,
childAspectRatio: 1.25,
children: <Widget>[
ActionItem(
icon: const Icon(FontAwesomeIcons.download),
onTap: () => {},
text: '离线缓存',
),
ActionItem(
icon: const Icon(FontAwesomeIcons.clockRotateLeft),
onTap: () => {},
text: '历史记录',
),
ActionItem(
icon: const Icon(FontAwesomeIcons.star),
onTap: () => {},
text: '我的收藏',
),
ActionItem(
icon: const Icon(FontAwesomeIcons.film),
onTap: () => {},
text: '稍后再看',
),
],
),
);
},
),
),
],
);
},
),
),
);
@ -217,10 +246,7 @@ class ActionItem extends StatelessWidget {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon!.icon!,
color: Theme.of(context).colorScheme.outline,
),
Icon(icon!.icon!),
const SizedBox(height: 8),
Text(
text!,

View File

@ -69,9 +69,4 @@ class PreviewController extends GetxController {
File(path).writeAsBytesSync(response.data);
Share.shareXFiles([XFile(path)], subject: imgList[initialPage.value]);
}
// 浏览器中查看
void onBrowserImg() async {
Utils.openURL(imgList[initialPage.value]);
}
}

View File

@ -74,11 +74,6 @@ class _ImagePreviewState extends State<ImagePreview>
onTap: _previewController.onSaveImg,
child: const Text('保存'),
),
PopupMenuItem(
value: 'browser',
onTap: _previewController.onBrowserImg,
child: const Text('浏览器中查看'),
),
],
),
],

View File

@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
@ -246,8 +247,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
child: Row(
children: const [
Icon(
FontAwesomeIcons.lemon,
size: 15,
CupertinoIcons.plus,
size: 16,
),
SizedBox(width: 4),
Text('关注'),
@ -383,7 +384,7 @@ class ActionItem extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon!.icon!,
size: 20,
size: 21,
color: selectStatus
? Theme.of(context).primaryColor
: Theme.of(context).colorScheme.outline),

View File

@ -18,15 +18,15 @@ class ReplyItem extends StatelessWidget {
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(12, 8, 8, 2),
padding: const EdgeInsets.fromLTRB(12, 6, 8, 0),
child: content(context),
),
Divider(
height: 1,
indent: 52,
endIndent: 10,
color: Theme.of(context).dividerColor.withOpacity(0.08),
)
// Divider(
// height: 1,
// indent: 52,
// endIndent: 10,
// color: Theme.of(context).dividerColor.withOpacity(0.08),
// )
],
),
);
@ -154,7 +154,7 @@ class ReplyItem extends StatelessWidget {
),
// title
Container(
margin: const EdgeInsets.only(top: 0, left: 45, right: 6),
margin: const EdgeInsets.only(top: 0, left: 45, right: 6, bottom: 6),
child: SelectableRegion(
magnifierConfiguration: const TextMagnifierConfiguration(),
focusNode: FocusNode(),
@ -201,7 +201,7 @@ class ReplyItem extends StatelessWidget {
.copyWith(color: Theme.of(context).colorScheme.outline),
),
if (replyItem!.replyControl != null &&
replyItem!.replyControl!.location != null)
replyItem!.replyControl!.location != '')
Text(
'${replyItem!.replyControl!.location!}',
style: Theme.of(context)
@ -315,10 +315,6 @@ class ReplyItemRow extends StatelessWidget {
maxLines: extraRow == 1 ? 2 : null,
TextSpan(
children: [
if (replies![index].isUp)
WidgetSpan(
child: UpTag(),
),
TextSpan(
text: replies![index].member.uname + ' ',
style: TextStyle(
@ -333,6 +329,10 @@ class ReplyItemRow extends StatelessWidget {
print('跳转至用户主页'),
},
),
if (replies![index].isUp)
WidgetSpan(
child: UpTag(),
),
buildContent(context, replies![index].content),
],
),
@ -352,13 +352,14 @@ class ReplyItemRow extends StatelessWidget {
useRootNavigator: true,
isScrollControlled: true,
Container(
height: Get.size.height - Get.size.width * 9 / 16 - 50,
height: Get.size.height - Get.size.width * 9 / 16 - 45,
color: Theme.of(context).colorScheme.background,
child: Column(
children: [
AppBar(
automaticallyImplyLeading: false,
centerTitle: false,
elevation: 1,
title: Text(
'评论详情',
style: Theme.of(context).textTheme.titleMedium,
@ -367,7 +368,6 @@ class ReplyItemRow extends StatelessWidget {
IconButton(
icon: const Icon(Icons.close),
onPressed: () async {
await Future.delayed(const Duration(milliseconds: 200));
Get.back();
},
)
@ -546,7 +546,7 @@ InlineSpan buildContent(BuildContext context, content) {
arguments: {'initialPage': 0, 'imgList': picList});
},
child: Padding(
padding: EdgeInsets.only(top: 4),
padding: const EdgeInsets.only(top: 4),
child: NetworkImgLayer(
src: pictureItem['img_src'],
width: box.maxWidth / 2,
@ -634,8 +634,8 @@ class UpTag extends StatelessWidget {
Widget build(BuildContext context) {
Color primary = Theme.of(context).colorScheme.primary;
return Container(
width: tagText == 'UP' ? 25 : 32,
height: tagText == 'UP' ? 16 : 18,
width: 24,
height: 15,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
color: tagText == 'UP' ? primary : null,

View File

@ -2,6 +2,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/http/constants.dart';
import 'package:pilipala/http/user.dart';
import 'package:pilipala/pages/mine/index.dart';
import 'package:pilipala/utils/cookie.dart';
import 'package:webview_cookie_manager/webview_cookie_manager.dart';
import 'package:webview_flutter/webview_flutter.dart';
@ -45,10 +46,10 @@ class WebviewController extends GetxController {
await SetCookie.onSet(cookies, HttpString.baseUrl);
await SetCookie.onSet(apiCookies, HttpString.baseApiUrl);
var result = await UserHttp.userInfo();
bool isLogin = result['data']['isLogin'];
if (isLogin) {
if (result['status'] && result['data'].isLogin) {
SmartDialog.showToast('登录成功');
Get.back();
Get.find<MineController>().userInfo = result['data'];
// Get.back();
}
} catch (e) {
print(e);