mod: 样式
This commit is contained in:
BIN
assets/fonts/ArchivoNarrow-BoldItalic.ttf
Normal file
BIN
assets/fonts/ArchivoNarrow-BoldItalic.ttf
Normal file
Binary file not shown.
@ -59,7 +59,7 @@ class _VideoCardHSkeletonState extends State<VideoCardHSkeleton> {
|
|||||||
.colorScheme
|
.colorScheme
|
||||||
.onInverseSurface,
|
.onInverseSurface,
|
||||||
width: 200,
|
width: 200,
|
||||||
height: 13,
|
height: 11,
|
||||||
margin: const EdgeInsets.only(bottom: 5),
|
margin: const EdgeInsets.only(bottom: 5),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
|
@ -25,12 +25,6 @@ class VideoCardVSkeleton extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).colorScheme.background,
|
color: Theme.of(context).colorScheme.background,
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
border: Border.all(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.outline
|
|
||||||
.withOpacity(0.1),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -23,8 +23,8 @@ class VideoReplySkeleton extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Container(
|
Container(
|
||||||
width: 120,
|
width: 80,
|
||||||
height: 16,
|
height: 13,
|
||||||
color: bgColor,
|
color: bgColor,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@ -40,28 +40,28 @@ class VideoReplySkeleton extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
width: 300,
|
width: 300,
|
||||||
height: 16,
|
height: 14,
|
||||||
margin: const EdgeInsets.only(bottom: 4),
|
margin: const EdgeInsets.only(bottom: 4),
|
||||||
color: bgColor,
|
color: bgColor,
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
width: 180,
|
width: 180,
|
||||||
height: 16,
|
height: 14,
|
||||||
margin: const EdgeInsets.only(bottom: 6),
|
margin: const EdgeInsets.only(bottom: 10),
|
||||||
color: bgColor,
|
color: bgColor,
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
width: 60,
|
width: 40,
|
||||||
height: 16,
|
height: 14,
|
||||||
margin: const EdgeInsets.only(bottom: 4),
|
margin: const EdgeInsets.only(bottom: 4),
|
||||||
color: bgColor,
|
color: bgColor,
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Container(
|
Container(
|
||||||
width: 60,
|
width: 40,
|
||||||
height: 16,
|
height: 14,
|
||||||
margin: const EdgeInsets.only(bottom: 4),
|
margin: const EdgeInsets.only(bottom: 4),
|
||||||
color: bgColor,
|
color: bgColor,
|
||||||
),
|
),
|
||||||
|
@ -27,7 +27,11 @@ class MyApp extends StatelessWidget {
|
|||||||
ColorScheme.fromSeed(
|
ColorScheme.fromSeed(
|
||||||
seedColor: Colors.green, brightness: Brightness.light),
|
seedColor: Colors.green, brightness: Brightness.light),
|
||||||
useMaterial3: true),
|
useMaterial3: true),
|
||||||
darkTheme: ThemeData(colorScheme: darkDynamic, useMaterial3: true),
|
darkTheme: ThemeData(
|
||||||
|
colorScheme: darkDynamic ??
|
||||||
|
ColorScheme.fromSeed(
|
||||||
|
seedColor: Colors.green, brightness: Brightness.dark),
|
||||||
|
useMaterial3: true),
|
||||||
getPages: Routes.getPages,
|
getPages: Routes.getPages,
|
||||||
home: const MainApp(),
|
home: const MainApp(),
|
||||||
// home: const Scaffold(),
|
// home: const Scaffold(),
|
||||||
|
@ -6,6 +6,7 @@ class ReplyContent {
|
|||||||
this.emote, // 表情包 如果有的话 null
|
this.emote, // 表情包 如果有的话 null
|
||||||
this.jumpUrl, // {}
|
this.jumpUrl, // {}
|
||||||
this.pictures, // {}
|
this.pictures, // {}
|
||||||
|
this.vote,
|
||||||
});
|
});
|
||||||
|
|
||||||
String? message;
|
String? message;
|
||||||
@ -14,6 +15,7 @@ class ReplyContent {
|
|||||||
Map? emote;
|
Map? emote;
|
||||||
Map? jumpUrl;
|
Map? jumpUrl;
|
||||||
List? pictures;
|
List? pictures;
|
||||||
|
Map? vote;
|
||||||
|
|
||||||
ReplyContent.fromJson(Map<String, dynamic> json) {
|
ReplyContent.fromJson(Map<String, dynamic> json) {
|
||||||
message = json['message'];
|
message = json['message'];
|
||||||
@ -22,5 +24,6 @@ class ReplyContent {
|
|||||||
emote = json['emote'] ?? {};
|
emote = json['emote'] ?? {};
|
||||||
jumpUrl = json['jump_url'] ?? {};
|
jumpUrl = json['jump_url'] ?? {};
|
||||||
pictures = json['pictures'] ?? [];
|
pictures = json['pictures'] ?? [];
|
||||||
|
vote = json['vote'] ?? {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
|
||||||
class HomeAppBar extends StatelessWidget {
|
class HomeAppBar extends StatelessWidget {
|
||||||
const HomeAppBar({super.key});
|
const HomeAppBar({super.key});
|
||||||
@ -29,19 +30,26 @@ class HomeAppBar extends StatelessWidget {
|
|||||||
title: const Text(
|
title: const Text(
|
||||||
'PiLiPaLa',
|
'PiLiPaLa',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 19,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
letterSpacing: 1,
|
letterSpacing: 1,
|
||||||
|
fontFamily: 'ArchivoNarrow',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
icon: const Icon(Icons.notifications_none_rounded),
|
icon: const FaIcon(
|
||||||
|
FontAwesomeIcons.magnifyingGlass,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
icon: const Icon(Icons.search_rounded),
|
icon: const FaIcon(
|
||||||
|
FontAwesomeIcons.envelope,
|
||||||
|
size: 20,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10)
|
const SizedBox(width: 10)
|
||||||
],
|
],
|
||||||
|
@ -19,7 +19,7 @@ class _MainAppState extends State<MainApp> with SingleTickerProviderStateMixin {
|
|||||||
late AnimationController? _animationController;
|
late AnimationController? _animationController;
|
||||||
late Animation<double>? _fadeAnimation;
|
late Animation<double>? _fadeAnimation;
|
||||||
late Animation<double>? _slideAnimation;
|
late Animation<double>? _slideAnimation;
|
||||||
int selectedIndex = 0;
|
int selectedIndex = 2;
|
||||||
int? _lastSelectTime; //上次点击时间
|
int? _lastSelectTime; //上次点击时间
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:pilipala/common/constants.dart';
|
||||||
|
|
||||||
class MinePage extends StatefulWidget {
|
class MinePage extends StatefulWidget {
|
||||||
const MinePage({super.key});
|
const MinePage({super.key});
|
||||||
@ -12,7 +14,187 @@ class _MinePageState extends State<MinePage> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('我的'),
|
title: null,
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.light_mode_rounded),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const FaIcon(
|
||||||
|
FontAwesomeIcons.sliders,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 12, right: 12),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
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(height: 20),
|
||||||
|
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),
|
||||||
|
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: '稍后再看',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActionItem extends StatelessWidget {
|
||||||
|
Icon? icon;
|
||||||
|
Function? onTap;
|
||||||
|
String? text;
|
||||||
|
|
||||||
|
ActionItem({
|
||||||
|
Key? key,
|
||||||
|
this.icon,
|
||||||
|
this.onTap,
|
||||||
|
this.text,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: () {},
|
||||||
|
borderRadius: StyleString.mdRadius,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(icon!.icon!),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(
|
||||||
|
text!,
|
||||||
|
style: Theme.of(context).textTheme.labelMedium,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pilipala/common/constants.dart';
|
import 'package:pilipala/common/constants.dart';
|
||||||
@ -114,116 +115,29 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SliverPadding(
|
return SliverPadding(
|
||||||
padding: const EdgeInsets.only(left: 12, right: 12, top: 25),
|
padding: const EdgeInsets.only(left: 12, right: 12, top: 20),
|
||||||
sliver: SliverToBoxAdapter(
|
sliver: SliverToBoxAdapter(
|
||||||
child: !widget.loadingStatus || videoItem.isNotEmpty
|
child: !widget.loadingStatus || videoItem.isNotEmpty
|
||||||
? Column(
|
? Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
SelectableRegion(
|
||||||
children: [
|
magnifierConfiguration: const TextMagnifierConfiguration(),
|
||||||
NetworkImgLayer(
|
focusNode: FocusNode(),
|
||||||
type: 'avatar',
|
selectionControls: MaterialTextSelectionControls(),
|
||||||
src: !widget.loadingStatus
|
child: Text(
|
||||||
? widget.videoDetail!.owner!.face
|
|
||||||
: videoItem['owner'].face,
|
|
||||||
width: 38,
|
|
||||||
height: 38,
|
|
||||||
fadeInDuration: Duration.zero,
|
|
||||||
fadeOutDuration: Duration.zero,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 14),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(!widget.loadingStatus
|
|
||||||
? widget.videoDetail!.owner!.name
|
|
||||||
: videoItem['owner'].name),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
Text(
|
|
||||||
widget.loadingStatus
|
|
||||||
? '- 粉丝'
|
|
||||||
: '${Utils.numFormat(widget.videoIntroController!.userStat['follower'])}粉丝',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.labelSmall!
|
|
||||||
.fontSize,
|
|
||||||
color: Theme.of(context).colorScheme.outline),
|
|
||||||
)
|
|
||||||
]),
|
|
||||||
const Spacer(),
|
|
||||||
AnimatedOpacity(
|
|
||||||
opacity: widget.loadingStatus ? 0 : 1,
|
|
||||||
duration: const Duration(milliseconds: 150),
|
|
||||||
child: SizedBox(
|
|
||||||
height: 35,
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: () {}, child: const Text('+ 关注')),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 13),
|
|
||||||
// 标题 超过两行收起
|
|
||||||
// Container(
|
|
||||||
// color: Colors.blue[50],
|
|
||||||
// child: SizedOverflowBox(
|
|
||||||
// size: const Size(50.0, 50.0),
|
|
||||||
// alignment: AlignmentDirectional.bottomStart,
|
|
||||||
// child: Container(height: 150.0, width: 150.0, color: Colors.blue,),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// Row(
|
|
||||||
// children: [
|
|
||||||
// Expanded(
|
|
||||||
// child: ExpandedSection(
|
|
||||||
// expand: false,
|
|
||||||
// begin: 1,
|
|
||||||
// end: 1,
|
|
||||||
// child: Text(
|
|
||||||
// !widget.loadingStatus
|
|
||||||
// ? widget.videoDetail!.title
|
|
||||||
// : videoItem['title'],
|
|
||||||
// overflow: TextOverflow.ellipsis,
|
|
||||||
// maxLines: 1,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// const SizedBox(width: 10),
|
|
||||||
// RotationTransition(
|
|
||||||
// turns: _manualAnimation!,
|
|
||||||
// child: IconButton(
|
|
||||||
// onPressed: () {
|
|
||||||
// /// 获取动画当前的值
|
|
||||||
// var value = _manualController!.value;
|
|
||||||
|
|
||||||
// /// 0.5代表 180弧度
|
|
||||||
// if (value == 0) {
|
|
||||||
// _manualController!.animateTo(0.5);
|
|
||||||
// } else {
|
|
||||||
// _manualController!.animateTo(0);
|
|
||||||
// }
|
|
||||||
// setState(() {
|
|
||||||
// isExpand = !isExpand;
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// icon: const Icon(Icons.expand_less)),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
|
|
||||||
Text(
|
|
||||||
!widget.loadingStatus
|
!widget.loadingStatus
|
||||||
? widget.videoDetail!.title
|
? widget.videoDetail!.title
|
||||||
: videoItem['title'],
|
: videoItem['title'],
|
||||||
|
style: Theme.of(context).textTheme.titleMedium!.copyWith(
|
||||||
|
letterSpacing: 0.5,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
// const SizedBox(height: 5),
|
|
||||||
// 播放量、评论、日期
|
|
||||||
|
|
||||||
InkWell(
|
InkWell(
|
||||||
splashColor: Colors.transparent,
|
splashColor: Colors.transparent,
|
||||||
|
hoverColor: Colors.transparent,
|
||||||
|
highlightColor: Colors.transparent,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_manualController!.animateTo(isExpand ? 0 : 0.5);
|
_manualController!.animateTo(isExpand ? 0 : 0.5);
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -276,8 +190,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.expand_less,
|
FontAwesomeIcons.angleUp,
|
||||||
size: 22,
|
size: 15,
|
||||||
color: Theme.of(context).colorScheme.outline,
|
color: Theme.of(context).colorScheme.outline,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -287,8 +201,65 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
// const SizedBox(height: 5),
|
Row(
|
||||||
|
children: [
|
||||||
|
NetworkImgLayer(
|
||||||
|
type: 'avatar',
|
||||||
|
src: !widget.loadingStatus
|
||||||
|
? widget.videoDetail!.owner!.face
|
||||||
|
: videoItem['owner'].face,
|
||||||
|
width: 38,
|
||||||
|
height: 38,
|
||||||
|
fadeInDuration: Duration.zero,
|
||||||
|
fadeOutDuration: Duration.zero,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 14),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(!widget.loadingStatus
|
||||||
|
? widget.videoDetail!.owner!.name
|
||||||
|
: videoItem['owner'].name),
|
||||||
|
// const SizedBox(width: 10),
|
||||||
|
Text(
|
||||||
|
widget.loadingStatus
|
||||||
|
? '- 粉丝'
|
||||||
|
: '${Utils.numFormat(widget.videoIntroController!.userStat['follower'])}粉丝',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelSmall!
|
||||||
|
.fontSize,
|
||||||
|
color: Theme.of(context).colorScheme.outline),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
AnimatedOpacity(
|
||||||
|
opacity: widget.loadingStatus ? 0 : 1,
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 36,
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: Row(
|
||||||
|
children: const [
|
||||||
|
Icon(
|
||||||
|
FontAwesomeIcons.lemon,
|
||||||
|
size: 17,
|
||||||
|
),
|
||||||
|
SizedBox(width: 4),
|
||||||
|
Text('关注'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
// 简介 默认收起
|
// 简介 默认收起
|
||||||
if (!widget.loadingStatus)
|
if (!widget.loadingStatus)
|
||||||
ExpandedSection(
|
ExpandedSection(
|
||||||
@ -320,8 +291,8 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 5),
|
||||||
_actionGrid(context),
|
_actionGrid(context),
|
||||||
// const SizedBox(height: 5),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: const Center(child: CircularProgressIndicator()),
|
: const Center(child: CircularProgressIndicator()),
|
||||||
@ -333,14 +304,15 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
Widget _actionGrid(BuildContext context) {
|
Widget _actionGrid(BuildContext context) {
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: constraints.maxWidth / 5,
|
height: constraints.maxWidth / 5 * 0.8,
|
||||||
child: GridView.count(
|
child: GridView.count(
|
||||||
primary: false,
|
primary: false,
|
||||||
padding: const EdgeInsets.all(0),
|
padding: const EdgeInsets.all(0),
|
||||||
crossAxisCount: 5,
|
crossAxisCount: 5,
|
||||||
|
childAspectRatio: 1.25,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
ActionItem(
|
ActionItem(
|
||||||
icon: const Icon(Icons.thumb_up),
|
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||||
onTap: () => {},
|
onTap: () => {},
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: widget.loadingStatus,
|
loadingStatus: widget.loadingStatus,
|
||||||
@ -348,13 +320,13 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
? widget.videoDetail!.stat!.like!.toString()
|
? widget.videoDetail!.stat!.like!.toString()
|
||||||
: '-'),
|
: '-'),
|
||||||
ActionItem(
|
ActionItem(
|
||||||
icon: const Icon(Icons.thumb_down),
|
icon: const Icon(FontAwesomeIcons.thumbsDown),
|
||||||
onTap: () => {},
|
onTap: () => {},
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: widget.loadingStatus,
|
loadingStatus: widget.loadingStatus,
|
||||||
text: '不喜欢'),
|
text: '不喜欢'),
|
||||||
ActionItem(
|
ActionItem(
|
||||||
icon: const Icon(Icons.generating_tokens),
|
icon: const Icon(FontAwesomeIcons.b),
|
||||||
onTap: () => {},
|
onTap: () => {},
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: widget.loadingStatus,
|
loadingStatus: widget.loadingStatus,
|
||||||
@ -362,7 +334,10 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
? widget.videoDetail!.stat!.coin!.toString()
|
? widget.videoDetail!.stat!.coin!.toString()
|
||||||
: '-'),
|
: '-'),
|
||||||
ActionItem(
|
ActionItem(
|
||||||
icon: const Icon(Icons.star),
|
icon: const Icon(
|
||||||
|
FontAwesomeIcons.heart,
|
||||||
|
size: 17,
|
||||||
|
),
|
||||||
onTap: () => {},
|
onTap: () => {},
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: widget.loadingStatus,
|
loadingStatus: widget.loadingStatus,
|
||||||
@ -370,7 +345,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
? widget.videoDetail!.stat!.favorite!.toString()
|
? widget.videoDetail!.stat!.favorite!.toString()
|
||||||
: '-'),
|
: '-'),
|
||||||
ActionItem(
|
ActionItem(
|
||||||
icon: const Icon(Icons.share),
|
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||||
onTap: () => {},
|
onTap: () => {},
|
||||||
selectStatus: false,
|
selectStatus: false,
|
||||||
loadingStatus: widget.loadingStatus,
|
loadingStatus: widget.loadingStatus,
|
||||||
@ -424,12 +399,14 @@ class ActionItem extends StatelessWidget {
|
|||||||
color: selectStatus
|
color: selectStatus
|
||||||
? Theme.of(context).primaryColor
|
? Theme.of(context).primaryColor
|
||||||
: Theme.of(context).colorScheme.outline,
|
: Theme.of(context).colorScheme.outline,
|
||||||
fontSize: Theme.of(context).textTheme.labelSmall?.fontSize),
|
fontSize:
|
||||||
|
Theme.of(context).textTheme.labelSmall?.fontSize),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/skeleton/video_card_h.dart';
|
import 'package:pilipala/common/skeleton/video_card_h.dart';
|
||||||
import 'package:pilipala/common/widgets/video_card_h.dart';
|
import 'package:pilipala/common/widgets/video_card_h.dart';
|
||||||
|
import 'package:pilipala/common/widgets/video_card_v.dart';
|
||||||
import './controller.dart';
|
import './controller.dart';
|
||||||
|
|
||||||
class RelatedVideoPanel extends StatefulWidget {
|
class RelatedVideoPanel extends StatefulWidget {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
import 'package:pilipala/models/video/reply/item.dart';
|
import 'package:pilipala/models/video/reply/item.dart';
|
||||||
@ -327,7 +328,8 @@ class ReplyItemRow extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -382,6 +384,7 @@ InlineSpan buildContent(BuildContext context, content) {
|
|||||||
if (content.emote.isEmpty &&
|
if (content.emote.isEmpty &&
|
||||||
content.atNameToMid.isEmpty &&
|
content.atNameToMid.isEmpty &&
|
||||||
content.jumpUrl.isEmpty &&
|
content.jumpUrl.isEmpty &&
|
||||||
|
content.vote.isEmpty &&
|
||||||
content.pictures.isEmpty) {
|
content.pictures.isEmpty) {
|
||||||
return TextSpan(text: content.message);
|
return TextSpan(text: content.message);
|
||||||
}
|
}
|
||||||
@ -416,7 +419,7 @@ InlineSpan buildContent(BuildContext context, content) {
|
|||||||
String matchMember = str;
|
String matchMember = str;
|
||||||
if (content.atNameToMid.isNotEmpty) {
|
if (content.atNameToMid.isNotEmpty) {
|
||||||
matchMember = str.splitMapJoin(
|
matchMember = str.splitMapJoin(
|
||||||
RegExp(r"@.*:"),
|
RegExp(r"@.*( |:)"),
|
||||||
onMatch: (Match match) {
|
onMatch: (Match match) {
|
||||||
if (match[0] != null) {
|
if (match[0] != null) {
|
||||||
content.atNameToMid.forEach((key, value) {
|
content.atNameToMid.forEach((key, value) {
|
||||||
@ -455,7 +458,6 @@ InlineSpan buildContent(BuildContext context, content) {
|
|||||||
RegExp("(?:${urlKeys.join("|")})"),
|
RegExp("(?:${urlKeys.join("|")})"),
|
||||||
onMatch: (Match match) {
|
onMatch: (Match match) {
|
||||||
String matchStr = match[0]!;
|
String matchStr = match[0]!;
|
||||||
// spanChilds.add(TextSpan(text: matchStr));
|
|
||||||
spanChilds.add(
|
spanChilds.add(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: content.jumpUrl[matchStr]['title'],
|
text: content.jumpUrl[matchStr]['title'],
|
||||||
@ -468,6 +470,16 @@ InlineSpan buildContent(BuildContext context, content) {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
spanChilds.add(
|
||||||
|
WidgetSpan(
|
||||||
|
child: Icon(
|
||||||
|
FontAwesomeIcons.magnifyingGlass,
|
||||||
|
size: 9,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
alignment: PlaceholderAlignment.top,
|
||||||
|
),
|
||||||
|
);
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
onNonMatch: (String str) {
|
onNonMatch: (String str) {
|
||||||
@ -477,6 +489,29 @@ InlineSpan buildContent(BuildContext context, content) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
str = matchUrl.splitMapJoin(
|
||||||
|
RegExp(r"\d{1,2}:\d{1,2}"),
|
||||||
|
onMatch: (Match match) {
|
||||||
|
String matchStr = match[0]!;
|
||||||
|
spanChilds.add(
|
||||||
|
TextSpan(
|
||||||
|
text: ' $matchStr ',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () => {
|
||||||
|
print('time 点击'),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
onNonMatch: (str) {
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
if (content.atNameToMid.isEmpty && content.jumpUrl.isEmpty) {
|
if (content.atNameToMid.isEmpty && content.jumpUrl.isEmpty) {
|
||||||
spanChilds.add(TextSpan(text: str));
|
spanChilds.add(TextSpan(text: str));
|
||||||
}
|
}
|
||||||
@ -486,9 +521,40 @@ InlineSpan buildContent(BuildContext context, content) {
|
|||||||
|
|
||||||
// 图片渲染
|
// 图片渲染
|
||||||
if (content.pictures.isNotEmpty) {
|
if (content.pictures.isNotEmpty) {
|
||||||
List<Widget> list = [];
|
|
||||||
List picList = [];
|
List picList = [];
|
||||||
int len = content.pictures.length;
|
int len = content.pictures.length;
|
||||||
|
if (len == 1) {
|
||||||
|
Map pictureItem = content.pictures.first;
|
||||||
|
picList.add(pictureItem['img_src']);
|
||||||
|
spanChilds.add(const TextSpan(text: '\n'));
|
||||||
|
spanChilds.add(
|
||||||
|
WidgetSpan(
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (context, BoxConstraints box) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Get.toNamed('/preview',
|
||||||
|
arguments: {'initialPage': 0, 'imgList': picList});
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(top: 4),
|
||||||
|
child: NetworkImgLayer(
|
||||||
|
src: pictureItem['img_src'],
|
||||||
|
width: box.maxWidth / 2,
|
||||||
|
height: box.maxWidth *
|
||||||
|
0.5 *
|
||||||
|
pictureItem['img_height'] /
|
||||||
|
pictureItem['img_width'],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (len > 1) {
|
||||||
|
List<Widget> list = [];
|
||||||
for (var i = 0; i < len; i++) {
|
for (var i = 0; i < len; i++) {
|
||||||
picList.add(content.pictures[i]['img_src']);
|
picList.add(content.pictures[i]['img_src']);
|
||||||
list.add(
|
list.add(
|
||||||
@ -547,6 +613,7 @@ InlineSpan buildContent(BuildContext context, content) {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// spanChilds.add(TextSpan(text: matchMember));
|
// spanChilds.add(TextSpan(text: matchMember));
|
||||||
return TextSpan(children: spanChilds);
|
return TextSpan(children: spanChilds);
|
||||||
}
|
}
|
||||||
@ -554,24 +621,25 @@ InlineSpan buildContent(BuildContext context, content) {
|
|||||||
class UpTag extends StatelessWidget {
|
class UpTag extends StatelessWidget {
|
||||||
String? tagText;
|
String? tagText;
|
||||||
UpTag({super.key, this.tagText = 'UP'});
|
UpTag({super.key, this.tagText = 'UP'});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
Color primary = Theme.of(context).colorScheme.primary;
|
||||||
return Container(
|
return Container(
|
||||||
width: tagText == 'UP' ? 28 : 38,
|
width: tagText == 'UP' ? 25 : 32,
|
||||||
height: tagText == 'UP' ? 17 : 19,
|
height: tagText == 'UP' ? 16 : 18,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(3),
|
borderRadius: BorderRadius.circular(3),
|
||||||
// color: Theme.of(context).colorScheme.primary,
|
color: tagText == 'UP' ? primary : null,
|
||||||
border: Border.all(color: Theme.of(context).colorScheme.primary)),
|
border: Border.all(color: primary)),
|
||||||
margin: const EdgeInsets.only(right: 4),
|
margin: const EdgeInsets.only(right: 4),
|
||||||
// padding: const EdgeInsets.symmetric(vertical: 0.5, horizontal: 4),
|
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
tagText!,
|
tagText!,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: Theme.of(context).textTheme.labelSmall!.fontSize,
|
fontSize: 10,
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: tagText == 'UP'
|
||||||
|
? Theme.of(context).colorScheme.onPrimary
|
||||||
|
: primary,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -272,6 +272,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
font_awesome_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: font_awesome_flutter
|
||||||
|
sha256: "959ef4add147753f990b4a7c6cccb746d5792dbdc81b1cde99e62e7edb31b206"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "10.4.0"
|
||||||
get:
|
get:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -65,6 +65,7 @@ dependencies:
|
|||||||
flutter_inappwebview: 5.4.4
|
flutter_inappwebview: 5.4.4
|
||||||
|
|
||||||
extended_nested_scroll_view: ^6.0.0
|
extended_nested_scroll_view: ^6.0.0
|
||||||
|
font_awesome_flutter: ^10.4.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@ -106,6 +107,9 @@ flutter:
|
|||||||
- family: fansCard
|
- family: fansCard
|
||||||
fonts:
|
fonts:
|
||||||
- asset: assets/fonts/fansCard.ttf
|
- asset: assets/fonts/fansCard.ttf
|
||||||
|
- family: ArchivoNarrow
|
||||||
|
fonts:
|
||||||
|
- asset: assets/fonts/ArchivoNarrow-BoldItalic.ttf
|
||||||
|
|
||||||
|
|
||||||
# For details regarding fonts from package dependencies,
|
# For details regarding fonts from package dependencies,
|
||||||
|
Reference in New Issue
Block a user