Compare commits

..

10 Commits

Author SHA1 Message Date
dom
f52bbe9804 upgrade dep
Signed-off-by: dom <githubaccount56556@proton.me>
2026-04-05 12:12:10 +08:00
dom
3ec54868d0 show reserve btn in space page
Signed-off-by: dom <githubaccount56556@proton.me>
2026-04-05 12:11:47 +08:00
dom
c0b55f9af3 show member guard
Signed-off-by: dom <githubaccount56556@proton.me>
2026-04-05 12:11:36 +08:00
dom
279f21857d clean up models
Signed-off-by: dom <githubaccount56556@proton.me>
2026-04-05 12:11:22 +08:00
dom
b897103af0 Upgrade deps
Signed-off-by: dom <githubaccount56556@proton.me>
2026-04-03 09:39:03 +08:00
dom
353664fbd4 Open offline dir on desktop
Signed-off-by: dom <githubaccount56556@proton.me>
2026-04-03 09:35:32 +08:00
dom
de3505ce07 Floating NavBar
Signed-off-by: dom <githubaccount56556@proton.me>
2026-04-03 09:35:32 +08:00
dom
cdc1720358 Reformat
Signed-off-by: dom <githubaccount56556@proton.me>
2026-04-03 09:35:25 +08:00
dom
904d210ba2 build
Signed-off-by: dom <githubaccount56556@proton.me>
2026-04-02 12:45:08 +08:00
HCha
db8dd85b63 fix: revert commit 7ee6d1e element.weight (#1879) 2026-04-02 12:44:35 +08:00
385 changed files with 2196 additions and 6671 deletions

View File

@@ -57,7 +57,6 @@ jobs:
mv dist/**/*.exe PiliPlus-Win-Setup/PiliPlus_windows_${{env.version}}_x64_setup.exe
- name: Compress
if: ${{ github.event.inputs.tag != '' }}
run: |
Compress-Archive -Path "Release/PiliPlus-Win" -DestinationPath "PiliPlus_windows_${{env.version}}_x64_portable.zip"
shell: pwsh
@@ -75,9 +74,9 @@ jobs:
- name: Upload windows file release
uses: actions/upload-artifact@v7
with:
archive: true
name: PiliPlus_windows_${{env.version}}_x64_portable
path: Release
archive: false
name: Windows-file-x64-release
path: PiliPlus_windows_*.zip
- name: Upload windows setup release
uses: actions/upload-artifact@v7

View File

@@ -5,11 +5,11 @@ import 'package:flutter/material.dart';
Widget avatars({
required ColorScheme colorScheme,
required Iterable<Owner> users,
double gap = 6.0,
}) {
const gap = 6.0;
const size = 22.0;
const padding = 0.8;
const offset = size - gap;
final offset = size - gap;
const imgSize = size - 2 * padding;
if (users.length == 1) {
return NetworkImgLayer(

View File

@@ -0,0 +1,777 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:PiliPlus/utils/extension/theme_ext.dart';
import 'package:flutter/material.dart';
const double _kMaxLabelTextScaleFactor = 1.3;
const _kNavigationHeight = 64.0;
const _kIndicatorHeight = _kNavigationHeight - 2 * _kIndicatorPaddingInt;
const _kIndicatorWidth = 86.0;
const _kIndicatorPaddingInt = 4.0;
const _kIndicatorPadding = EdgeInsets.all(_kIndicatorPaddingInt);
const _kBorderRadius = BorderRadius.all(.circular(_kNavigationHeight / 2));
const _kNavigationShape = RoundedSuperellipseBorder(
borderRadius: _kBorderRadius,
);
/// ref [NavigationBar]
class FloatingNavigationBar extends StatelessWidget {
// ignore: prefer_const_constructors_in_immutables
FloatingNavigationBar({
super.key,
this.animationDuration = const Duration(milliseconds: 500),
this.selectedIndex = 0,
required this.destinations,
this.onDestinationSelected,
this.backgroundColor,
this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.indicatorColor,
this.indicatorShape,
this.labelBehavior,
this.overlayColor,
this.labelTextStyle,
this.labelPadding,
this.bottomPadding = 8.0,
}) : assert(destinations.length >= 2),
assert(0 <= selectedIndex && selectedIndex < destinations.length);
final Duration animationDuration;
final int selectedIndex;
final List<Widget> destinations;
final ValueChanged<int>? onDestinationSelected;
final Color? backgroundColor;
final double? elevation;
final Color? shadowColor;
final Color? surfaceTintColor;
final Color? indicatorColor;
final ShapeBorder? indicatorShape;
final NavigationDestinationLabelBehavior? labelBehavior;
final WidgetStateProperty<Color?>? overlayColor;
final WidgetStateProperty<TextStyle?>? labelTextStyle;
final EdgeInsetsGeometry? labelPadding;
final double bottomPadding;
VoidCallback _handleTap(int index) {
return onDestinationSelected != null
? () => onDestinationSelected!(index)
: () {};
}
@override
Widget build(BuildContext context) {
final defaults = _NavigationBarDefaultsM3(context);
final navigationBarTheme = NavigationBarTheme.of(context);
final effectiveLabelBehavior =
labelBehavior ??
navigationBarTheme.labelBehavior ??
defaults.labelBehavior!;
final padding = MediaQuery.viewPaddingOf(context);
return UnconstrainedBox(
child: Padding(
padding: .fromLTRB(
padding.left,
0,
padding.right,
bottomPadding + padding.bottom,
),
child: SizedBox(
height: _kNavigationHeight,
width: destinations.length * _kIndicatorWidth,
child: DecoratedBox(
decoration: ShapeDecoration(
color: ElevationOverlay.applySurfaceTint(
backgroundColor ??
navigationBarTheme.backgroundColor ??
defaults.backgroundColor!,
surfaceTintColor ??
navigationBarTheme.surfaceTintColor ??
defaults.surfaceTintColor,
elevation ??
navigationBarTheme.elevation ??
defaults.elevation!,
),
shape: RoundedSuperellipseBorder(
side: defaults.borderSide,
borderRadius: _kBorderRadius,
),
),
child: Padding(
padding: _kIndicatorPadding,
child: Row(
crossAxisAlignment: .stretch,
children: <Widget>[
for (int i = 0; i < destinations.length; i++)
Expanded(
child: _SelectableAnimatedBuilder(
duration: animationDuration,
isSelected: i == selectedIndex,
builder: (context, animation) {
return _NavigationDestinationInfo(
index: i,
selectedIndex: selectedIndex,
totalNumberOfDestinations: destinations.length,
selectedAnimation: animation,
labelBehavior: effectiveLabelBehavior,
indicatorColor: indicatorColor,
indicatorShape: indicatorShape,
overlayColor: overlayColor,
onTap: _handleTap(i),
labelTextStyle: labelTextStyle,
labelPadding: labelPadding,
child: destinations[i],
);
},
),
),
],
),
),
),
),
),
);
}
}
class FloatingNavigationDestination extends StatelessWidget {
const FloatingNavigationDestination({
super.key,
required this.icon,
this.selectedIcon,
required this.label,
this.tooltip,
this.enabled = true,
});
final Widget icon;
final Widget? selectedIcon;
final String label;
final String? tooltip;
final bool enabled;
@override
Widget build(BuildContext context) {
final info = _NavigationDestinationInfo.of(context);
const selectedState = <WidgetState>{WidgetState.selected};
const unselectedState = <WidgetState>{};
const disabledState = <WidgetState>{WidgetState.disabled};
final navigationBarTheme = NavigationBarTheme.of(context);
final defaults = _NavigationBarDefaultsM3(context);
final animation = info.selectedAnimation;
return Stack(
alignment: .center,
clipBehavior: .none,
children: [
NavigationIndicator(
animation: animation,
color:
info.indicatorColor ??
navigationBarTheme.indicatorColor ??
defaults.indicatorColor!,
),
_NavigationDestinationBuilder(
label: label,
tooltip: tooltip,
enabled: enabled,
buildIcon: (context) {
final IconThemeData selectedIconTheme =
navigationBarTheme.iconTheme?.resolve(selectedState) ??
defaults.iconTheme!.resolve(selectedState)!;
final IconThemeData unselectedIconTheme =
navigationBarTheme.iconTheme?.resolve(unselectedState) ??
defaults.iconTheme!.resolve(unselectedState)!;
final IconThemeData disabledIconTheme =
navigationBarTheme.iconTheme?.resolve(disabledState) ??
defaults.iconTheme!.resolve(disabledState)!;
final Widget selectedIconWidget = IconTheme.merge(
data: enabled ? selectedIconTheme : disabledIconTheme,
child: selectedIcon ?? icon,
);
final Widget unselectedIconWidget = IconTheme.merge(
data: enabled ? unselectedIconTheme : disabledIconTheme,
child: icon,
);
return _StatusTransitionWidgetBuilder(
animation: animation,
builder: (context, child) {
return animation.isForwardOrCompleted
? selectedIconWidget
: unselectedIconWidget;
},
);
},
buildLabel: (context) {
final TextStyle? effectiveSelectedLabelTextStyle =
info.labelTextStyle?.resolve(selectedState) ??
navigationBarTheme.labelTextStyle?.resolve(selectedState) ??
defaults.labelTextStyle!.resolve(selectedState);
final TextStyle? effectiveUnselectedLabelTextStyle =
info.labelTextStyle?.resolve(unselectedState) ??
navigationBarTheme.labelTextStyle?.resolve(unselectedState) ??
defaults.labelTextStyle!.resolve(unselectedState);
final TextStyle? effectiveDisabledLabelTextStyle =
info.labelTextStyle?.resolve(disabledState) ??
navigationBarTheme.labelTextStyle?.resolve(disabledState) ??
defaults.labelTextStyle!.resolve(disabledState);
final EdgeInsetsGeometry labelPadding =
info.labelPadding ??
navigationBarTheme.labelPadding ??
defaults.labelPadding!;
final textStyle = enabled
? animation.isForwardOrCompleted
? effectiveSelectedLabelTextStyle
: effectiveUnselectedLabelTextStyle
: effectiveDisabledLabelTextStyle;
return Padding(
padding: labelPadding,
child: MediaQuery.withClampedTextScaling(
maxScaleFactor: _kMaxLabelTextScaleFactor,
child: Text(label, style: textStyle),
),
);
},
),
],
);
}
}
class _NavigationDestinationBuilder extends StatefulWidget {
const _NavigationDestinationBuilder({
required this.buildIcon,
required this.buildLabel,
required this.label,
this.tooltip,
this.enabled = true,
});
final WidgetBuilder buildIcon;
final WidgetBuilder buildLabel;
final String label;
final String? tooltip;
final bool enabled;
@override
State<_NavigationDestinationBuilder> createState() =>
_NavigationDestinationBuilderState();
}
class _NavigationDestinationBuilderState
extends State<_NavigationDestinationBuilder> {
final GlobalKey iconKey = GlobalKey();
@override
Widget build(BuildContext context) {
final info = _NavigationDestinationInfo.of(context);
final child = GestureDetector(
behavior: .opaque,
onTap: widget.enabled ? info.onTap : null,
child: _NavigationBarDestinationLayout(
icon: widget.buildIcon(context),
iconKey: iconKey,
label: widget.buildLabel(context),
),
);
if (info.labelBehavior == .alwaysShow) {
return child;
}
return _NavigationBarDestinationTooltip(
message: widget.tooltip ?? widget.label,
child: child,
);
}
}
class _NavigationDestinationInfo extends InheritedWidget {
const _NavigationDestinationInfo({
required this.index,
required this.selectedIndex,
required this.totalNumberOfDestinations,
required this.selectedAnimation,
required this.labelBehavior,
required this.indicatorColor,
required this.indicatorShape,
required this.overlayColor,
required this.onTap,
this.labelTextStyle,
this.labelPadding,
required super.child,
});
final int index;
final int selectedIndex;
final int totalNumberOfDestinations;
final Animation<double> selectedAnimation;
final NavigationDestinationLabelBehavior labelBehavior;
final Color? indicatorColor;
final ShapeBorder? indicatorShape;
final WidgetStateProperty<Color?>? overlayColor;
final VoidCallback onTap;
final WidgetStateProperty<TextStyle?>? labelTextStyle;
final EdgeInsetsGeometry? labelPadding;
static _NavigationDestinationInfo of(BuildContext context) {
final _NavigationDestinationInfo? result = context
.dependOnInheritedWidgetOfExactType<_NavigationDestinationInfo>();
assert(
result != null,
'Navigation destinations need a _NavigationDestinationInfo parent, '
'which is usually provided by NavigationBar.',
);
return result!;
}
@override
bool updateShouldNotify(_NavigationDestinationInfo oldWidget) {
return index != oldWidget.index ||
totalNumberOfDestinations != oldWidget.totalNumberOfDestinations ||
selectedAnimation != oldWidget.selectedAnimation ||
labelBehavior != oldWidget.labelBehavior ||
onTap != oldWidget.onTap;
}
}
class NavigationIndicator extends StatelessWidget {
const NavigationIndicator({
super.key,
required this.animation,
this.color,
this.width = _kIndicatorWidth,
this.height = _kIndicatorHeight,
});
final Animation<double> animation;
final Color? color;
final double width;
final double height;
static final _anim = Tween<double>(
begin: .5,
end: 1.0,
).chain(CurveTween(curve: Curves.easeInOutCubicEmphasized));
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: animation,
builder: (context, child) {
final double scale = animation.isDismissed
? 0.0
: _anim.evaluate(animation);
return Transform(
alignment: Alignment.center,
transform: Matrix4.diagonal3Values(scale, 1.0, 1.0),
child: child,
);
},
child: _StatusTransitionWidgetBuilder(
animation: animation,
builder: (context, child) {
return _SelectableAnimatedBuilder(
isSelected: animation.isForwardOrCompleted,
duration: const Duration(milliseconds: 100),
alwaysDoFullAnimation: true,
builder: (context, fadeAnimation) {
return FadeTransition(
opacity: fadeAnimation,
child: DecoratedBox(
decoration: ShapeDecoration(
shape: _kNavigationShape,
color: color ?? Theme.of(context).colorScheme.secondary,
),
child: const SizedBox(
width: _kIndicatorWidth,
height: _kIndicatorHeight,
),
),
);
},
);
},
),
);
}
}
class _NavigationBarDestinationLayout extends StatelessWidget {
const _NavigationBarDestinationLayout({
required this.icon,
required this.iconKey,
required this.label,
});
final Widget icon;
final GlobalKey iconKey;
final Widget label;
@override
Widget build(BuildContext context) {
return _DestinationLayoutAnimationBuilder(
builder: (context, animation) {
return CustomMultiChildLayout(
delegate: _NavigationDestinationLayoutDelegate(animation: animation),
children: <Widget>[
LayoutId(
id: _NavigationDestinationLayoutDelegate.iconId,
child: KeyedSubtree(key: iconKey, child: icon),
),
LayoutId(
id: _NavigationDestinationLayoutDelegate.labelId,
child: FadeTransition(
alwaysIncludeSemantics: true,
opacity: animation,
child: label,
),
),
],
);
},
);
}
}
class _DestinationLayoutAnimationBuilder extends StatelessWidget {
const _DestinationLayoutAnimationBuilder({required this.builder});
final Widget Function(BuildContext, Animation<double>) builder;
@override
Widget build(BuildContext context) {
final info = _NavigationDestinationInfo.of(context);
switch (info.labelBehavior) {
case NavigationDestinationLabelBehavior.alwaysShow:
return builder(context, kAlwaysCompleteAnimation);
case NavigationDestinationLabelBehavior.alwaysHide:
return builder(context, kAlwaysDismissedAnimation);
case NavigationDestinationLabelBehavior.onlyShowSelected:
return _CurvedAnimationBuilder(
animation: info.selectedAnimation,
curve: Curves.easeInOutCubicEmphasized,
reverseCurve: Curves.easeInOutCubicEmphasized.flipped,
builder: builder,
);
}
}
}
class _NavigationBarDestinationTooltip extends StatelessWidget {
const _NavigationBarDestinationTooltip({
required this.message,
required this.child,
});
final String message;
final Widget child;
@override
Widget build(BuildContext context) {
return Tooltip(
message: message,
verticalOffset: 34,
excludeFromSemantics: true,
preferBelow: false,
child: child,
);
}
}
class _NavigationDestinationLayoutDelegate extends MultiChildLayoutDelegate {
_NavigationDestinationLayoutDelegate({required this.animation})
: super(relayout: animation);
final Animation<double> animation;
static const int iconId = 1;
static const int labelId = 2;
@override
void performLayout(Size size) {
double halfWidth(Size size) => size.width / 2;
double halfHeight(Size size) => size.height / 2;
final Size iconSize = layoutChild(iconId, BoxConstraints.loose(size));
final Size labelSize = layoutChild(labelId, BoxConstraints.loose(size));
final double yPositionOffset = Tween<double>(
begin: halfHeight(iconSize),
end: halfHeight(iconSize) + halfHeight(labelSize),
).transform(animation.value);
final double iconYPosition = halfHeight(size) - yPositionOffset;
positionChild(
iconId,
Offset(
halfWidth(size) - halfWidth(iconSize),
iconYPosition,
),
);
positionChild(
labelId,
Offset(
halfWidth(size) - halfWidth(labelSize),
iconYPosition + iconSize.height,
),
);
}
@override
bool shouldRelayout(_NavigationDestinationLayoutDelegate oldDelegate) {
return oldDelegate.animation != animation;
}
}
class _StatusTransitionWidgetBuilder extends StatusTransitionWidget {
const _StatusTransitionWidgetBuilder({
required super.animation,
required this.builder,
// ignore: unused_element_parameter
this.child,
});
final TransitionBuilder builder;
final Widget? child;
@override
Widget build(BuildContext context) => builder(context, child);
}
class _SelectableAnimatedBuilder extends StatefulWidget {
const _SelectableAnimatedBuilder({
required this.isSelected,
this.duration = const Duration(milliseconds: 200),
this.alwaysDoFullAnimation = false,
required this.builder,
});
final bool isSelected;
final Duration duration;
final bool alwaysDoFullAnimation;
final Widget Function(BuildContext, Animation<double>) builder;
@override
_SelectableAnimatedBuilderState createState() =>
_SelectableAnimatedBuilderState();
}
class _SelectableAnimatedBuilderState extends State<_SelectableAnimatedBuilder>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
_controller.duration = widget.duration;
_controller.value = widget.isSelected ? 1.0 : 0.0;
}
@override
void didUpdateWidget(_SelectableAnimatedBuilder oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.duration != widget.duration) {
_controller.duration = widget.duration;
}
if (oldWidget.isSelected != widget.isSelected) {
if (widget.isSelected) {
_controller.forward(from: widget.alwaysDoFullAnimation ? 0 : null);
} else {
_controller.reverse(from: widget.alwaysDoFullAnimation ? 1 : null);
}
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.builder(context, _controller);
}
}
class _CurvedAnimationBuilder extends StatefulWidget {
const _CurvedAnimationBuilder({
required this.animation,
required this.curve,
required this.reverseCurve,
required this.builder,
});
final Animation<double> animation;
final Curve curve;
final Curve reverseCurve;
final Widget Function(BuildContext, Animation<double>) builder;
@override
_CurvedAnimationBuilderState createState() => _CurvedAnimationBuilderState();
}
class _CurvedAnimationBuilderState extends State<_CurvedAnimationBuilder> {
late AnimationStatus _animationDirection;
AnimationStatus? _preservedDirection;
@override
void initState() {
super.initState();
_animationDirection = widget.animation.status;
_updateStatus(widget.animation.status);
widget.animation.addStatusListener(_updateStatus);
}
@override
void dispose() {
widget.animation.removeStatusListener(_updateStatus);
super.dispose();
}
void _updateStatus(AnimationStatus status) {
if (_animationDirection != status) {
setState(() {
_animationDirection = status;
});
}
switch (status) {
case AnimationStatus.forward || AnimationStatus.reverse
when _preservedDirection != null:
break;
case AnimationStatus.forward || AnimationStatus.reverse:
setState(() {
_preservedDirection = status;
});
case AnimationStatus.completed || AnimationStatus.dismissed:
setState(() {
_preservedDirection = null;
});
}
}
@override
Widget build(BuildContext context) {
final shouldUseForwardCurve =
(_preservedDirection ?? _animationDirection) != AnimationStatus.reverse;
final Animation<double> curvedAnimation = CurveTween(
curve: shouldUseForwardCurve ? widget.curve : widget.reverseCurve,
).animate(widget.animation);
return widget.builder(context, curvedAnimation);
}
}
const _indicatorDark = Color(0x15FFFFFF);
const _indicatorLight = Color(0x10000000);
class _NavigationBarDefaultsM3 extends NavigationBarThemeData {
_NavigationBarDefaultsM3(this.context)
: super(
height: _kNavigationHeight,
elevation: 3.0,
labelBehavior: NavigationDestinationLabelBehavior.alwaysShow,
);
final BuildContext context;
late final _colors = Theme.of(context).colorScheme;
late final _textTheme = Theme.of(context).textTheme;
BorderSide get borderSide => _colors.brightness.isDark
? const BorderSide(color: Color(0x08FFFFFF))
: const BorderSide(color: Color(0x08000000));
@override
Color? get backgroundColor => _colors.surfaceContainer;
@override
Color? get shadowColor => Colors.transparent;
@override
Color? get surfaceTintColor => Colors.transparent;
@override
WidgetStateProperty<IconThemeData?>? get iconTheme {
return WidgetStateProperty.resolveWith((Set<WidgetState> states) {
return IconThemeData(
size: 24.0,
color: states.contains(WidgetState.disabled)
? _colors.onSurfaceVariant.withValues(alpha: 0.38)
: states.contains(WidgetState.selected)
? _colors.onSecondaryContainer
: _colors.onSurfaceVariant,
);
});
}
@override
Color? get indicatorColor =>
_colors.brightness.isDark ? _indicatorDark : _indicatorLight;
@override
ShapeBorder? get indicatorShape => const StadiumBorder();
@override
WidgetStateProperty<TextStyle?>? get labelTextStyle {
return WidgetStateProperty.resolveWith((Set<WidgetState> states) {
final TextStyle style = _textTheme.labelMedium!;
return style.apply(
color: states.contains(WidgetState.disabled)
? _colors.onSurfaceVariant.withValues(alpha: 0.38)
: states.contains(WidgetState.selected)
? _colors.onSurface
: _colors.onSurfaceVariant,
);
});
}
@override
EdgeInsetsGeometry? get labelPadding => const EdgeInsets.only(top: 2);
}

View File

@@ -830,6 +830,10 @@ abstract final class Api {
static const String dynReserve = '/x/dynamic/feed/reserve/click';
static const String spaceReserve = '/x/space/reserve';
static const String spaceReserveCancel = '/x/space/reserve/cancel';
static const String favPugv = '/pugv/app/web/favorite/page';
static const String addFavPugv = '/pugv/app/web/favorite/add';
@@ -997,4 +1001,7 @@ abstract final class Api {
static const String liveMedalWall =
'${HttpString.liveBaseUrl}/xlive/web-ucenter/user/MedalWall';
static const String memberGuard =
'${HttpString.liveBaseUrl}/xlive/app-ucenter/v1/guard/MainGuardCardAll';
}

View File

@@ -21,6 +21,7 @@ import 'package:PiliPlus/models_new/member/coin_like_arc/data.dart';
import 'package:PiliPlus/models_new/member/search_archive/data.dart';
import 'package:PiliPlus/models_new/member/season_web/data.dart';
import 'package:PiliPlus/models_new/member_card_info/data.dart';
import 'package:PiliPlus/models_new/member_guard/data.dart';
import 'package:PiliPlus/models_new/space/space/data.dart';
import 'package:PiliPlus/models_new/space/space_archive/data.dart';
import 'package:PiliPlus/models_new/space/space_article/data.dart';
@@ -830,4 +831,23 @@ abstract final class MemberHttp {
return Error(res.data['message']);
}
}
static Future<LoadingState<MemberGuardData>> memberGuard({
required Object ruid,
required int page,
}) async {
final res = await Request().get(
Api.memberGuard,
queryParameters: {
'page': page,
'page_size': 20,
'ruid': ruid,
},
);
if (res.data['code'] == 0) {
return Success(MemberGuardData.fromJson(res.data['data']));
} else {
return Error(res.data['message']);
}
}
}

View File

@@ -431,7 +431,9 @@ abstract final class UserHttp {
}
}
static Future<LoadingState<void>> spaceSettingMod(Map data) async {
static Future<LoadingState<void>> spaceSettingMod(
Map<String, dynamic> data,
) async {
final res = await Request().post(
Api.spaceSettingMod,
queryParameters: {
@@ -569,4 +571,23 @@ abstract final class UserHttp {
return Error(res.data['message']);
}
}
static Future<LoadingState<void>> spaceReserve({
required Object sid,
required bool isFollow,
}) async {
final res = await Request().post(
isFollow ? Api.spaceReserveCancel : Api.spaceReserve,
data: {
'sid': sid,
'csrf': Accounts.main.csrf,
},
options: Options(contentType: Headers.formUrlEncodedContentType),
);
if (res.data['code'] == 0) {
return const Success(null);
} else {
return Error(res.data['message']);
}
}
}

View File

@@ -2,7 +2,7 @@ enum AccountType {
main('主账号'),
heartbeat('记录观看'),
recommend('推荐'),
video('视频取流')
video('视频取流'),
;
final String title;

View File

@@ -3,7 +3,7 @@ enum AudioNormalization {
// ref https://github.com/KRTirtho/spotube/commit/da10ab2e291d4ba4d3082b9a6ae535639fb8f1b7
dynaudnorm('预设 dynaudnorm', 'dynaudnorm=g=5:f=250:r=0.9:p=0.5'),
loudnorm('预设 loudnorm', 'loudnorm=I=-16:LRA=11:TP=-1.5'),
custom('自定义参数')
custom('自定义参数'),
;
final String title;

View File

@@ -4,7 +4,7 @@ enum BadgeType {
none(),
vip('大会员'),
person('认证个人', Color(0xFFFFCC00)),
institution('认证机构', Colors.lightBlueAccent)
institution('认证机构', Colors.lightBlueAccent),
;
final String? desc;

View File

@@ -2,7 +2,7 @@ import 'package:PiliPlus/models/common/enum_with_label.dart';
enum BarHideType with EnumWithLabel {
instant('即时'),
sync('同步')
sync('同步'),
;
@override

View File

@@ -1,7 +1,7 @@
enum DmBlockType {
keyword('关键词'),
regex('正则'),
uid('用户')
uid('用户'),
;
final String label;

View File

@@ -1,7 +1,7 @@
enum DynamicBadgeMode {
hidden('隐藏'),
point('红点'),
number('数字')
number('数字'),
;
final String desc;

View File

@@ -3,7 +3,7 @@ enum DynamicsTabType {
video('投稿'),
pgc('番剧'),
article('专栏'),
up('UP')
up('UP'),
;
final String label;

View File

@@ -3,7 +3,7 @@ enum UpPanelPosition {
leftFixed('左侧常驻'),
rightFixed('右侧常驻'),
leftDrawer('左侧抽屉'),
rightDrawer('右侧抽屉')
rightDrawer('右侧抽屉'),
;
final String label;

View File

@@ -1,7 +1,7 @@
enum EpisodeType {
part('分P'),
season('合集'),
pgc('剧集')
pgc('剧集'),
;
final String title;

View File

@@ -1,7 +1,7 @@
enum FavOrderType {
mtime('最近收藏'),
view('最多播放'),
pubtime('最近投稿')
pubtime('最近投稿'),
;
final String label;

View File

@@ -13,7 +13,7 @@ enum FavTabType {
article('专栏', FavArticlePage()),
note('笔记', FavNotePage()),
topic('话题', FavTopicPage()),
cheese('课堂', FavCheesePage())
cheese('课堂', FavCheesePage()),
;
final String title;

View File

@@ -1,6 +1,6 @@
enum FollowOrderType {
def('', '最近关注'),
attention('attention', '最常访问')
attention('attention', '最常访问'),
;
final String type;

View File

@@ -19,7 +19,7 @@ enum HomeTabType implements EnumWithLabel {
hot('热门'),
rank('分区'),
bangumi('番剧'),
cinema('影视')
cinema('影视'),
;
@override

View File

@@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
enum LaterViewType {
all(0, '全部'),
// toView(1, '未看'),
unfinished(2, '未看完')
unfinished(2, '未看完'),
// viewed(3, '已看完'),
;

View File

@@ -4,7 +4,7 @@ enum LiveContributionRankType {
online_rank('在线榜', 'contribution_rank'),
daily_rank('日榜', 'today_rank'),
weekly_rank('周榜', 'current_week_rank'),
monthly_rank('月榜', 'current_month_rank')
monthly_rank('月榜', 'current_month_rank'),
;
final String title;

View File

@@ -6,7 +6,7 @@ enum ContributeType {
season(Api.spaceSeason),
series(Api.spaceSeries),
bangumi(Api.spaceBangumi),
comic(Api.spaceComic)
comic(Api.spaceComic),
;
final String api;

View File

@@ -8,7 +8,7 @@ enum MemberTabType {
favorite('收藏'),
bangumi('番剧'),
cheese('课堂'),
shop('小店')
shop('小店'),
;
static bool showMemberShop = Pref.showMemberShop;

View File

@@ -3,7 +3,7 @@ enum MsgUnReadType {
reply('回复我的'),
at('@我'),
like('收到的赞'),
sysMsg('系统通知')
sysMsg('系统通知'),
;
final String title;

View File

@@ -7,8 +7,8 @@ import 'package:flutter/material.dart';
enum NavigationBarType implements EnumWithLabel {
home(
'首页',
Icon(Icons.home_outlined, size: 23),
Icon(Icons.home, size: 21),
Icon(Icons.home_outlined, size: 24),
Icon(Icons.home, size: 24),
HomePage(),
),
dynamics(
@@ -19,10 +19,10 @@ enum NavigationBarType implements EnumWithLabel {
),
mine(
'我的',
Icon(Icons.person_outline, size: 21),
Icon(Icons.person, size: 21),
Icon(Icons.person_outline, size: 24),
Icon(Icons.person, size: 24),
MinePage(),
)
),
;
@override

View File

@@ -2,7 +2,7 @@ import 'package:PiliPlus/http/api.dart';
enum PgcReviewType {
long(label: '长评', api: Api.pgcReviewL),
short(label: '短评', api: Api.pgcReviewS)
short(label: '短评', api: Api.pgcReviewS),
;
final String label;
@@ -15,7 +15,7 @@ enum PgcReviewType {
enum PgcReviewSortType {
def('默认', 0),
latest('最新', 1)
latest('最新', 1),
;
final int sort;

View File

@@ -19,7 +19,7 @@ enum RankType {
documentary('记录', seasonType: 3),
movie('电影', seasonType: 2),
tv('剧集', seasonType: 5),
variety('综艺', seasonType: 7)
variety('综艺', seasonType: 7),
;
final String label;

View File

@@ -4,7 +4,7 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart
enum ReplyOptionType {
allow('允许评论'),
close('关闭评论'),
choose('精选评论')
choose('精选评论'),
;
final String title;

View File

@@ -1,7 +1,7 @@
enum ReplySortType {
time('最新评论', '最新'),
hot('最热评论', '最热'),
select('精选评论', '精选')
select('精选评论', '精选'),
;
final String title;

View File

@@ -3,7 +3,7 @@ enum ArticleOrderType {
pubdate('最新发布'),
click('最多点击'),
attention('最多喜欢'),
scores('最多评论')
scores('最多评论'),
;
String get order => name;
@@ -20,7 +20,7 @@ enum ArticleZoneType {
interest('兴趣', 29),
novel('轻小说', 16),
tech('科技', 17),
note('笔记', 41)
note('笔记', 41),
;
final String label;

View File

@@ -18,7 +18,7 @@ enum SearchType {
// 用户bili_user
bili_user('用户'),
// 专栏article
article('专栏')
article('专栏'),
;
// 相簿photo
// photo

View File

@@ -3,7 +3,7 @@ enum UserOrderType {
fansDesc('粉丝数由高到低', 0, 'fans'),
fansAsc('粉丝数由低到高', 1, 'fans'),
levelDesc('Lv等级由高到低', 0, 'level'),
levelAsc('Lv等级由低到高', 1, 'level')
levelAsc('Lv等级由低到高', 1, 'level'),
;
final String label;
@@ -16,7 +16,7 @@ enum UserType {
all('全部用户'),
up('UP主'),
common('普通用户'),
verified('认证用户')
verified('认证用户'),
;
final String label;

View File

@@ -2,7 +2,7 @@ enum VideoPubTimeType {
all('不限'),
day('最近一天'),
week('最近一周'),
halfYear('最近半年')
halfYear('最近半年'),
;
final String label;
@@ -14,7 +14,7 @@ enum VideoDurationType {
tenMins('0-10分钟'),
halfHour('10-30分钟'),
hour('30-60分钟'),
hourPlus('60分钟+')
hourPlus('60分钟+'),
;
final String label;
@@ -43,7 +43,7 @@ enum VideoZoneType {
cinephile('影视', tids: 181),
documentary('记录', tids: 177),
movie('电影', tids: 23),
tv('电视', tids: 11)
tv('电视', tids: 11),
;
final String label;
@@ -58,7 +58,7 @@ enum ArchiveFilterType {
pubdate('新发布'),
dm('弹幕多'),
stow('收藏多'),
scores('评论多')
scores('评论多'),
;
// 专栏
// attention('最多喜欢'),

View File

@@ -6,7 +6,7 @@ enum SettingType {
styleSetting('外观设置'),
extraSetting('其它设置'),
webdavSetting('WebDAV 设置'),
about('关于')
about('关于'),
;
final String title;

View File

@@ -2,7 +2,7 @@ enum ActionType {
skip('跳过'),
mute('静音'),
full('整个视频'),
poi('精彩时刻')
poi('精彩时刻'),
;
final String title;

View File

@@ -5,7 +5,7 @@ enum SkipType implements EnumWithLabel {
skipOnce('跳过一次'),
skipManually('手动跳过'),
showOnly('仅显示'),
disable('禁用')
disable('禁用'),
;
@override

View File

@@ -7,7 +7,7 @@ enum StatType {
reply(Icons.comment_outlined, '评论'),
follow(Icons.favorite_border, '关注'),
play(Icons.play_circle_outlined, '播放'),
listen(Icons.headset_outlined, '播放')
listen(Icons.headset_outlined, '播放'),
;
final IconData iconData;

View File

@@ -3,7 +3,7 @@ import 'package:PiliPlus/models/common/enum_with_label.dart';
enum SuperResolutionType with EnumWithLabel {
disable('禁用'),
efficiency('效率'),
quality('画质')
quality('画质'),
;
@override

View File

@@ -4,7 +4,7 @@ import 'package:material_design_icons_flutter/material_design_icons_flutter.dart
enum ThemeType {
light('浅色'),
dark('深色'),
system('跟随系统')
system('跟随系统'),
;
final String desc;

View File

@@ -7,7 +7,7 @@ enum AudioQuality {
dolby_30255(30255, '杜比全景声'),
k192(30280, '192K'),
k132(30232, '132K'),
k64(30216, '64K')
k64(30216, '64K'),
;
final int code;

View File

@@ -24,7 +24,7 @@ enum CDNService {
aliov('aliov阿里云海外', 'upos-sz-mirroraliov.bilivideo.com'),
cosov('cosov腾讯云海外', 'upos-sz-mirrorcosov.bilivideo.com'),
hwov('hwov华为云海外', 'upos-sz-mirrorhwov.bilivideo.com'),
hk_bcache('hk_bcacheBilibili海外', 'cn-hk-eq-bcache-01.bilivideo.com')
hk_bcache('hk_bcacheBilibili海外', 'cn-hk-eq-bcache-01.bilivideo.com'),
;
final String desc;

View File

@@ -7,7 +7,7 @@ enum LiveQuality {
bluRay(400, '蓝光'),
superHD(250, '超清'),
smooth(150, '高清'),
flunt(80, '流畅')
flunt(80, '流畅'),
;
final int code;

View File

@@ -26,7 +26,7 @@ enum SourceType {
extraId: 4,
playlistSource: PlaylistSource.MEDIA_LIST,
),
file
file,
;
final int? mediaType;

View File

@@ -2,7 +2,7 @@ enum SubtitlePrefType {
off('默认不显示字幕'),
on('优先选择非自动生成(ai)字幕'),
withoutAi('跳过自动生成(ai)字幕,选择第一个可用字幕'),
auto('静音时等同第二项,非静音时等同第三项')
auto('静音时等同第二项,非静音时等同第三项'),
;
final String desc;

View File

@@ -4,7 +4,7 @@ enum VideoDecodeFormatType {
DVH1(['dvh1']),
AV1(['av01']),
HEVC(['hev1', 'hvc1']),
AVC(['avc1'])
AVC(['avc1']),
;
String get description => name;

View File

@@ -11,7 +11,7 @@ enum VideoQuality {
high720(64, '720P 准高清', '720P'),
clear480(32, '480P 标清', '480P'),
fluent360(16, '360P 流畅', '360P'),
speed240(6, '240P 极速', '240P')
speed240(6, '240P 极速', '240P'),
;
final int code;

View File

@@ -13,7 +13,7 @@ enum VideoType {
type: 10,
replyType: 33,
api: Api.pugvUrl,
)
),
;
final int type;

View File

@@ -4,7 +4,7 @@ enum WebviewMenuItem {
openInBrowser('浏览器中打开'),
clearCache('清除缓存'),
resetCookie('重新设置Cookie'),
goBack('返回')
goBack('返回'),
;
final String title;

View File

@@ -5,19 +5,7 @@ class AccountMyInfoData {
num? coins;
String? birthday;
String? face;
int? faceNftNew;
int? sex;
int? level;
int? rank;
int? silence;
int? emailStatus;
int? telStatus;
int? identification;
int? isTourist;
int? pinPrompting;
int? inRegAudit;
bool? hasFaceNft;
bool? setBirthday;
AccountMyInfoData({
this.mid,
@@ -26,19 +14,7 @@ class AccountMyInfoData {
this.coins,
this.birthday,
this.face,
this.faceNftNew,
this.sex,
this.level,
this.rank,
this.silence,
this.emailStatus,
this.telStatus,
this.identification,
this.isTourist,
this.pinPrompting,
this.inRegAudit,
this.hasFaceNft,
this.setBirthday,
});
factory AccountMyInfoData.fromJson(Map<String, dynamic> json) =>
@@ -49,18 +25,6 @@ class AccountMyInfoData {
coins: json['coins'] as num?,
birthday: json['birthday'] as String?,
face: json['face'] as String?,
faceNftNew: json['face_nft_new'] as int?,
sex: json['sex'] as int?,
level: json['level'] as int?,
rank: json['rank'] as int?,
silence: json['silence'] as int?,
emailStatus: json['email_status'] as int?,
telStatus: json['tel_status'] as int?,
identification: json['identification'] as int?,
isTourist: json['is_tourist'] as int?,
pinPrompting: json['pin_prompting'] as int?,
inRegAudit: json['in_reg_audit'] as int?,
hasFaceNft: json['has_face_nft'] as bool?,
setBirthday: json['set_birthday'] as bool?,
);
}

View File

@@ -1,86 +1,26 @@
import 'package:PiliPlus/models_new/article/article_info/share_channel.dart';
import 'package:PiliPlus/models_new/article/article_info/stats.dart';
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
class ArticleInfoData {
int? like;
bool? attention;
bool? favorite;
num? coin;
Stats? stats;
String? title;
String? bannerUrl;
int? mid;
String? authorName;
bool? isAuthor;
List<String>? imageUrls;
List<String>? originImageUrls;
bool? shareable;
bool? showLaterWatch;
bool? showSmallWindow;
bool? inList;
int? pre;
int? next;
List<ShareChannel>? shareChannels;
int? type;
String? videoUrl;
String? location;
bool? disableShare;
ArticleInfoData({
this.like,
this.attention,
this.favorite,
this.coin,
this.stats,
this.title,
this.bannerUrl,
this.mid,
this.authorName,
this.isAuthor,
this.imageUrls,
this.originImageUrls,
this.shareable,
this.showLaterWatch,
this.showSmallWindow,
this.inList,
this.pre,
this.next,
this.shareChannels,
this.type,
this.videoUrl,
this.location,
this.disableShare,
});
factory ArticleInfoData.fromJson(Map<String, dynamic> json) =>
ArticleInfoData(
like: json['like'] as int?,
attention: json['attention'] as bool?,
favorite: json['favorite'] as bool?,
coin: json['coin'] as num?,
stats: json['stats'] == null
? null
: Stats.fromJson(json['stats'] as Map<String, dynamic>),
title: json['title'] as String?,
bannerUrl: json['banner_url'] as String?,
mid: json['mid'] as int?,
authorName: json['author_name'] as String?,
isAuthor: json['is_author'] as bool?,
imageUrls: (json['image_urls'] as List?)?.fromCast(),
originImageUrls: (json['origin_image_urls'] as List?)?.fromCast(),
shareable: json['shareable'] as bool?,
showLaterWatch: json['show_later_watch'] as bool?,
showSmallWindow: json['show_small_window'] as bool?,
inList: json['in_list'] as bool?,
pre: json['pre'] as int?,
next: json['next'] as int?,
shareChannels: (json['share_channels'] as List<dynamic>?)
?.map((e) => ShareChannel.fromJson(e as Map<String, dynamic>))
.toList(),
type: json['type'] as int?,
videoUrl: json['video_url'] as String?,
location: json['location'] as String?,
disableShare: json['disable_share'] as bool?,
);
}

View File

@@ -1,13 +0,0 @@
class ShareChannel {
String? name;
String? picture;
String? shareChannel;
ShareChannel({this.name, this.picture, this.shareChannel});
factory ShareChannel.fromJson(Map<String, dynamic> json) => ShareChannel(
name: json['name'] as String?,
picture: json['picture'] as String?,
shareChannel: json['share_channel'] as String?,
);
}

View File

@@ -1,32 +1,20 @@
class Stats {
int? view;
int? favorite;
int? like;
int? dislike;
int? reply;
int? share;
num? coin;
int? dynam1c;
Stats({
this.view,
this.favorite,
this.like,
this.dislike,
this.reply,
this.share,
this.coin,
this.dynam1c,
});
factory Stats.fromJson(Map<String, dynamic> json) => Stats(
view: json['view'] as int?,
favorite: json['favorite'] as int?,
like: json['like'] as int?,
dislike: json['dislike'] as int?,
reply: json['reply'] as int?,
share: json['share'] as int?,
coin: json['coin'] as num?,
dynam1c: json['dynamic'] as int?,
);
}

View File

@@ -1,67 +1,32 @@
import 'package:PiliPlus/models_new/article/article_list/category.dart';
import 'package:PiliPlus/models_new/article/article_list/stats.dart';
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
class ArticleListItemModel {
int? id;
String? title;
int? state;
int? publishTime;
int? words;
List<String>? imageUrls;
Category? category;
List<Category>? categories;
String? summary;
int? type;
String? dynIdStr;
int? attributes;
int? authorUid;
int? onlyFans;
Stats? stats;
int? likeState;
ArticleListItemModel({
this.id,
this.title,
this.state,
this.publishTime,
this.words,
this.imageUrls,
this.category,
this.categories,
this.summary,
this.type,
this.dynIdStr,
this.attributes,
this.authorUid,
this.onlyFans,
this.stats,
this.likeState,
});
factory ArticleListItemModel.fromJson(Map<String, dynamic> json) =>
ArticleListItemModel(
id: json['id'] as int?,
title: json['title'] as String?,
state: json['state'] as int?,
publishTime: json['publish_time'] as int?,
words: json['words'] as int?,
imageUrls: (json['image_urls'] as List?)?.fromCast(),
category: json['category'] == null
? null
: Category.fromJson(json['category'] as Map<String, dynamic>),
categories: (json['categories'] as List<dynamic>?)
?.map((e) => Category.fromJson(e as Map<String, dynamic>))
.toList(),
summary: json['summary'] as String?,
type: json['type'] as int?,
dynIdStr: json['dyn_id_str'] as String?,
attributes: json['attributes'] as int?,
authorUid: json['author_uid'] as int?,
onlyFans: json['only_fans'] as int?,
stats: json['stats'] == null
? null
: Stats.fromJson(json['stats'] as Map<String, dynamic>),
likeState: json['like_state'] as int?,
);
}

View File

@@ -1,13 +0,0 @@
class Category {
int? id;
int? parentId;
String? name;
Category({this.id, this.parentId, this.name});
factory Category.fromJson(Map<String, dynamic> json) => Category(
id: json['id'] as int?,
parentId: json['parent_id'] as int?,
name: json['name'] as String?,
);
}

View File

@@ -1,21 +1,16 @@
import 'package:PiliPlus/models/model_owner.dart';
import 'package:PiliPlus/models_new/article/article_list/article.dart';
import 'package:PiliPlus/models_new/article/article_list/last.dart';
import 'package:PiliPlus/models_new/article/article_list/list.dart';
class ArticleListData {
ArticleListInfo? list;
List<ArticleListItemModel>? articles;
Owner? author;
Last? last;
bool? attention;
ArticleListData({
this.list,
this.articles,
this.author,
this.last,
this.attention,
});
factory ArticleListData.fromJson(Map<String, dynamic> json) =>
@@ -31,9 +26,5 @@ class ArticleListData {
author: json['author'] == null
? null
: Owner.fromJson(json['author'] as Map<String, dynamic>),
last: json['last'] == null
? null
: Last.fromJson(json['last'] as Map<String, dynamic>),
attention: json['attention'] as bool?,
);
}

View File

@@ -1,13 +0,0 @@
class Label {
String? path;
String? text;
String? labelTheme;
Label({this.path, this.text, this.labelTheme});
factory Label.fromJson(Map<String, dynamic> json) => Label(
path: json['path'] as String?,
text: json['text'] as String?,
labelTheme: json['label_theme'] as String?,
);
}

View File

@@ -1,55 +0,0 @@
import 'package:PiliPlus/models_new/article/article_list/category.dart';
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
class Last {
int? id;
String? title;
int? state;
int? publishTime;
int? words;
List<String>? imageUrls;
Category? category;
dynamic categories;
String? summary;
int? type;
String? dynIdStr;
int? attributes;
int? authorUid;
int? onlyFans;
Last({
this.id,
this.title,
this.state,
this.publishTime,
this.words,
this.imageUrls,
this.category,
this.categories,
this.summary,
this.type,
this.dynIdStr,
this.attributes,
this.authorUid,
this.onlyFans,
});
factory Last.fromJson(Map<String, dynamic> json) => Last(
id: json['id'] as int?,
title: json['title'] as String?,
state: json['state'] as int?,
publishTime: json['publish_time'] as int?,
words: json['words'] as int?,
imageUrls: (json['image_urls'] as List?)?.fromCast(),
category: json['category'] == null
? null
: Category.fromJson(json['category'] as Map<String, dynamic>),
categories: json['categories'] as dynamic,
summary: json['summary'] as String?,
type: json['type'] as int?,
dynIdStr: json['dyn_id_str'] as String?,
attributes: json['attributes'] as int?,
authorUid: json['author_uid'] as int?,
onlyFans: json['only_fans'] as int?,
);
}

View File

@@ -1,54 +1,30 @@
class ArticleListInfo {
int? id;
int? mid;
String? name;
String? imageUrl;
int? updateTime;
int? ctime;
int? publishTime;
String? summary;
int? words;
int? read;
int? articlesCount;
int? state;
String? reason;
String? applyTime;
String? checkTime;
ArticleListInfo({
this.id,
this.mid,
this.name,
this.imageUrl,
this.updateTime,
this.ctime,
this.publishTime,
this.summary,
this.words,
this.read,
this.articlesCount,
this.state,
this.reason,
this.applyTime,
this.checkTime,
});
factory ArticleListInfo.fromJson(Map<String, dynamic> json) =>
ArticleListInfo(
id: json['id'] as int?,
mid: json['mid'] as int?,
name: json['name'] as String?,
imageUrl: json['image_url'] as String?,
updateTime: json['update_time'] as int?,
ctime: json['ctime'] as int?,
publishTime: json['publish_time'] as int?,
summary: json['summary'] as String?,
words: json['words'] as int?,
read: json['read'] as int?,
articlesCount: json['articles_count'] as int?,
state: json['state'] as int?,
reason: json['reason'] as String?,
applyTime: json['apply_time'] as String?,
checkTime: json['check_time'] as String?,
);
}

View File

@@ -1,32 +1,17 @@
class Stats {
int? view;
int? favorite;
int? like;
int? dislike;
int? reply;
int? share;
num? coin;
int? dynam1c;
Stats({
this.view,
this.favorite,
this.like,
this.dislike,
this.reply,
this.share,
this.coin,
this.dynam1c,
});
factory Stats.fromJson(Map<String, dynamic> json) => Stats(
view: json['view'] as int?,
favorite: json['favorite'] as int?,
like: json['like'] as int?,
dislike: json['dislike'] as int?,
reply: json['reply'] as int?,
share: json['share'] as int?,
coin: json['coin'] as num?,
dynam1c: json['dynamic'] as int?,
);
}

View File

@@ -1,13 +0,0 @@
class Category {
int? id;
int? parentId;
String? name;
Category({this.id, this.parentId, this.name});
factory Category.fromJson(Map<String, dynamic> json) => Category(
id: json['id'] as int?,
parentId: json['parent_id'] as int?,
name: json['name'] as String?,
);
}

View File

@@ -1,95 +1,28 @@
import 'package:PiliPlus/models/model_avatar.dart';
import 'package:PiliPlus/models_new/article/article_view/category.dart';
import 'package:PiliPlus/models_new/article/article_view/media.dart';
import 'package:PiliPlus/models_new/article/article_view/ops.dart';
import 'package:PiliPlus/models_new/article/article_view/opus.dart';
import 'package:PiliPlus/models_new/article/article_view/stats.dart';
import 'package:PiliPlus/models_new/article/article_view/tag.dart';
import 'package:PiliPlus/utils/extension/iterable_ext.dart';
class ArticleViewData {
int? id;
Category? category;
List<Category>? categories;
String? title;
String? summary;
String? bannerUrl;
int? templateId;
int? state;
Avatar? author;
int? reprint;
List<String>? imageUrls;
int? publishTime;
int? ctime;
int? mtime;
Stats? stats;
List<Tag>? tags;
int? words;
List<String>? originImageUrls;
dynamic list;
bool? isLike;
Media? media;
String? applyTime;
String? checkTime;
int? original;
int? actId;
dynamic dispute;
dynamic authenMark;
int? coverAvid;
dynamic topVideoInfo;
int? type;
int? checkState;
int? originTemplateId;
int? privatePub;
dynamic contentPicList;
String? content;
String? keywords;
int? versionId;
String? dynIdStr;
int? totalArtNum;
ArticleOpus? opus;
List<ArticleOps>? ops;
ArticleViewData({
this.id,
this.category,
this.categories,
this.title,
this.summary,
this.bannerUrl,
this.templateId,
this.state,
this.author,
this.reprint,
this.imageUrls,
this.publishTime,
this.ctime,
this.mtime,
this.stats,
this.tags,
this.words,
this.originImageUrls,
this.list,
this.isLike,
this.media,
this.applyTime,
this.checkTime,
this.original,
this.actId,
this.dispute,
this.authenMark,
this.coverAvid,
this.topVideoInfo,
this.type,
this.checkState,
this.originTemplateId,
this.privatePub,
this.contentPicList,
this.content,
this.keywords,
this.versionId,
this.dynIdStr,
this.totalArtNum,
this.opus,
this.ops,
});
@@ -97,56 +30,14 @@ class ArticleViewData {
factory ArticleViewData.fromJson(Map<String, dynamic> json) =>
ArticleViewData(
id: json['id'] as int?,
category: json['category'] == null
? null
: Category.fromJson(json['category'] as Map<String, dynamic>),
categories: (json['categories'] as List<dynamic>?)
?.map((e) => Category.fromJson(e as Map<String, dynamic>))
.toList(),
title: json['title'] as String?,
summary: json['summary'] as String?,
bannerUrl: json['banner_url'] as String?,
templateId: json['template_id'] as int?,
state: json['state'] as int?,
author: json['author'] == null
? null
: Avatar.fromJson(json['author'] as Map<String, dynamic>),
reprint: json['reprint'] as int?,
imageUrls: (json['image_urls'] as List?)?.fromCast(),
publishTime: json['publish_time'] as int?,
ctime: json['ctime'] as int?,
mtime: json['mtime'] as int?,
stats: json['stats'] == null
? null
: Stats.fromJson(json['stats'] as Map<String, dynamic>),
tags: (json['tags'] as List<dynamic>?)
?.map((e) => Tag.fromJson(e as Map<String, dynamic>))
.toList(),
words: json['words'] as int?,
originImageUrls: (json['origin_image_urls'] as List?)?.fromCast(),
list: json['list'] as dynamic,
isLike: json['is_like'] as bool?,
media: json['media'] == null
? null
: Media.fromJson(json['media'] as Map<String, dynamic>),
applyTime: json['apply_time'] as String?,
checkTime: json['check_time'] as String?,
original: json['original'] as int?,
actId: json['act_id'] as int?,
dispute: json['dispute'] as dynamic,
authenMark: json['authenMark'] as dynamic,
coverAvid: json['cover_avid'] as int?,
topVideoInfo: json['top_video_info'] as dynamic,
type: json['type'] as int?,
checkState: json['check_state'] as int?,
originTemplateId: json['origin_template_id'] as int?,
privatePub: json['private_pub'] as int?,
contentPicList: json['content_pic_list'] as dynamic,
content: json['content'] as String?,
keywords: json['keywords'] as String?,
versionId: json['version_id'] as int?,
dynIdStr: json['dyn_id_str'] as String?,
totalArtNum: json['total_art_num'] as int?,
opus: json['opus'] == null
? null
: ArticleOpus.fromJson(json['opus'] as Map<String, dynamic>),

View File

@@ -1,13 +0,0 @@
class Label {
String? path;
String? text;
String? labelTheme;
Label({this.path, this.text, this.labelTheme});
factory Label.fromJson(Map<String, dynamic> json) => Label(
path: json['path'] as String?,
text: json['text'] as String?,
labelTheme: json['label_theme'] as String?,
);
}

View File

@@ -1,35 +0,0 @@
class Media {
int? score;
int? mediaId;
String? title;
String? cover;
String? area;
int? typeId;
String? typeName;
int? spoiler;
int? seasonId;
Media({
this.score,
this.mediaId,
this.title,
this.cover,
this.area,
this.typeId,
this.typeName,
this.spoiler,
this.seasonId,
});
factory Media.fromJson(Map<String, dynamic> json) => Media(
score: json['score'] as int?,
mediaId: json['media_id'] as int?,
title: json['title'] as String?,
cover: json['cover'] as String?,
area: json['area'] as String?,
typeId: json['type_id'] as int?,
typeName: json['type_name'] as String?,
spoiler: json['spoiler'] as int?,
seasonId: json['season_id'] as int?,
);
}

View File

@@ -1,15 +1,9 @@
import 'package:PiliPlus/models/dynamics/article_content_model.dart';
class ArticleOpus {
int? opusid;
int? opussource;
String? title;
List<ArticleContentModel>? content;
ArticleOpus.fromJson(Map<String, dynamic> json) {
opusid = json['opus_id'];
opussource = json['opus_source'];
title = json['title'];
if (json['content']?['paragraphs'] case List list) {
content = list.map((i) => ArticleContentModel.fromJson(i)).toList();
}

View File

@@ -1,32 +0,0 @@
class Stats {
int? view;
int? favorite;
int? like;
int? dislike;
int? reply;
int? share;
num? coin;
int? dynam1c;
Stats({
this.view,
this.favorite,
this.like,
this.dislike,
this.reply,
this.share,
this.coin,
this.dynam1c,
});
factory Stats.fromJson(Map<String, dynamic> json) => Stats(
view: json['view'] as int?,
favorite: json['favorite'] as int?,
like: json['like'] as int?,
dislike: json['dislike'] as int?,
reply: json['reply'] as int?,
share: json['share'] as int?,
coin: json['coin'] as num?,
dynam1c: json['dynamic'] as int?,
);
}

View File

@@ -1,11 +0,0 @@
class Tag {
int? tid;
String? name;
Tag({this.tid, this.name});
factory Tag.fromJson(Map<String, dynamic> json) => Tag(
tid: json['tid'] as int?,
name: json['name'] as String?,
);
}

View File

@@ -2,16 +2,14 @@ import 'package:PiliPlus/models_new/blacklist/list.dart';
class BlackListData {
List<BlackListItem>? list;
int? reVersion;
int? total;
BlackListData({this.list, this.reVersion, this.total});
BlackListData({this.list, this.total});
factory BlackListData.fromJson(Map<String, dynamic> json) => BlackListData(
list: (json['list'] as List<dynamic>?)
?.map((e) => BlackListItem.fromJson(e as Map<String, dynamic>))
.toList(),
reVersion: json['re_version'] as int?,
total: json['total'] as int?,
);
}

View File

@@ -1,61 +1,20 @@
import 'package:PiliPlus/models/model_avatar.dart';
class BlackListItem {
int? mid;
int? attribute;
int? mtime;
dynamic tag;
int? special;
String? uname;
String? face;
String? sign;
int? faceNft;
BaseOfficialVerify? officialVerify;
Vip? vip;
String? nftIcon;
String? recReason;
String? trackId;
String? followTime;
BlackListItem({
this.mid,
this.attribute,
this.mtime,
this.tag,
this.special,
this.uname,
this.face,
this.sign,
this.faceNft,
this.officialVerify,
this.vip,
this.nftIcon,
this.recReason,
this.trackId,
this.followTime,
});
factory BlackListItem.fromJson(Map<String, dynamic> json) => BlackListItem(
mid: json['mid'] as int?,
attribute: json['attribute'] as int?,
mtime: json['mtime'] as int?,
tag: json['tag'] as dynamic,
special: json['special'] as int?,
uname: json['uname'] as String?,
face: json['face'] as String?,
sign: json['sign'] as String?,
faceNft: json['face_nft'] as int?,
officialVerify: json['official_verify'] == null
? null
: BaseOfficialVerify.fromJson(
json['official_verify'] as Map<String, dynamic>,
),
vip: json['vip'] == null
? null
: Vip.fromJson(json['vip'] as Map<String, dynamic>),
nftIcon: json['nft_icon'] as String?,
recReason: json['rec_reason'] as String?,
trackId: json['track_id'] as String?,
followTime: json['follow_time'] as String?,
);
}

View File

@@ -1,15 +1,13 @@
import 'package:PiliPlus/models_new/coin_log/list.dart';
class CoinLogData {
List<CoinLogItem>? list;
int? count;
CoinLogData({this.list});
CoinLogData({this.list, this.count});
List<CoinLogItem>? list;
factory CoinLogData.fromJson(Map<String, dynamic> json) => CoinLogData(
list: (json['list'] as List<dynamic>?)
?.map((e) => CoinLogItem.fromJson(e as Map<String, dynamic>))
.toList(),
count: json['count'] as int?,
);
}

View File

@@ -1,14 +1,14 @@
class CoinLogItem {
final String time;
final String delta;
final String reason;
const CoinLogItem({
required this.time,
required this.delta,
required this.reason,
});
final String time;
final String delta;
final String reason;
factory CoinLogItem.fromJson(Map<String, dynamic> json) => CoinLogItem(
time: json['time'],
delta: (json['delta'] as num).toString(),

View File

@@ -1,31 +1,13 @@
class DanmakuPost {
DanmakuPost({
required this.action,
required this.animation,
required this.colorfulSrc,
required this.dmContent,
required this.dmid,
required this.dmidStr,
required this.visible,
});
final String? action;
final String? animation;
final dynamic colorfulSrc;
final String? dmContent;
final int? dmid;
final String? dmidStr;
final bool? visible;
factory DanmakuPost.fromJson(Map<String, dynamic> json) {
return DanmakuPost(
action: json["action"],
animation: json["animation"],
colorfulSrc: json["colorful_src"],
dmContent: json["dm_content"],
dmid: json["dmid"],
dmidStr: json["dmid_str"],
visible: json["visible"],
);
}
}

View File

@@ -1,8 +1,12 @@
import 'dart:io' show Platform, Process;
import 'package:PiliPlus/models/common/video/video_type.dart';
import 'package:PiliPlus/pages/common/multi_select/base.dart'
show MultiSelectData;
import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/route_manager.dart';
class BiliDownloadEntryInfo with MultiSelectData {
@@ -68,10 +72,7 @@ class BiliDownloadEntryInfo with MultiSelectData {
itemBuilder: (_) => [
PopupMenuItem(
height: 38,
child: const Text(
'查看详情页',
style: TextStyle(fontSize: 13),
),
child: const Text('查看详情页', style: TextStyle(fontSize: 13)),
onTap: () {
if (ep case final ep?) {
if (ep.from == VideoType.pugv.name) {
@@ -97,14 +98,34 @@ class BiliDownloadEntryInfo with MultiSelectData {
);
},
),
if (PlatformUtils.isDesktop)
PopupMenuItem(
height: 38,
child: const Text('打开本地文件夹', style: TextStyle(fontSize: 13)),
onTap: () async {
try {
final String executable;
if (Platform.isWindows) {
executable = 'explorer';
} else if (Platform.isMacOS) {
executable = 'open';
} else if (Platform.isLinux) {
executable = 'xdg-open';
} else {
throw UnimplementedError();
}
await Process.run(executable, [entryDirPath]);
} catch (e) {
SmartDialog.showToast(e.toString());
}
},
),
if (ownerId case final mid?)
PopupMenuItem(
height: 38,
child: Text(
'访问${ownerName != null ? '$ownerName' : '用户主页'}',
style: const TextStyle(
fontSize: 13,
),
style: const TextStyle(fontSize: 13),
),
onTap: () => Get.toNamed('/member?mid=$mid'),
),
@@ -395,7 +416,7 @@ enum DownloadStatus {
failDanmaku('获取弹幕失败'),
failPlayUrl('获取播放地址失败'),
pause('暂停中'),
wait('等待中')
wait('等待中'),
;
final String message;

View File

@@ -2,14 +2,12 @@ import 'package:PiliPlus/models_new/dynamic/dyn_mention/item.dart';
class MentionGroup {
String? groupName;
int? groupType;
List<MentionItem>? items;
MentionGroup({this.groupName, this.groupType, this.items});
MentionGroup({this.groupName, this.items});
factory MentionGroup.fromJson(Map<String, dynamic> json) => MentionGroup(
groupName: json['group_name'] as String?,
groupType: json['group_type'] as int?,
items: (json['items'] as List<dynamic>?)
?.map((e) => MentionItem.fromJson(e as Map<String, dynamic>))
.toList(),

View File

@@ -4,14 +4,12 @@ class MentionItem with MultiSelectData {
final String? face;
final int? fans;
final String? name;
final int? officialVerifyType;
final String? uid;
MentionItem({
this.face,
this.fans,
this.name,
this.officialVerifyType,
this.uid,
});
@@ -19,7 +17,6 @@ class MentionItem with MultiSelectData {
face: json['face'] as String?,
fans: json['fans'] as int?,
name: json['name'] as String?,
officialVerifyType: json['official_verify_type'] as int?,
uid: json['uid'] as String?,
);

View File

@@ -1,23 +1,17 @@
class DynReserveData {
int? finalBtnStatus;
int? btnMode;
int? reserveUpdate;
String? descUpdate;
String? toast;
DynReserveData({
this.finalBtnStatus,
this.btnMode,
this.reserveUpdate,
this.descUpdate,
this.toast,
});
factory DynReserveData.fromJson(Map<String, dynamic> json) => DynReserveData(
finalBtnStatus: json['final_btn_status'] as int?,
btnMode: json['btn_mode'] as int?,
reserveUpdate: json['reserve_update'] as int?,
descUpdate: json['desc_update'] as String?,
toast: json['toast'] as String?,
);
}

View File

@@ -1,48 +1,18 @@
class ReserveInfoData {
int? id;
String? title;
int? stime;
int? etime;
int? type;
int? livePlanStartTime;
int? lotteryType;
String? lotteryId;
int? subType;
ReserveInfoData({
this.id,
this.title,
this.stime,
this.etime,
this.type,
this.livePlanStartTime,
this.lotteryType,
this.lotteryId,
this.subType,
});
factory ReserveInfoData.fromJson(Map<String, dynamic> json) =>
ReserveInfoData(
id: json['id'] as int?,
title: json['title'] as String?,
stime: json['stime'] as int?,
etime: json['etime'] as int?,
type: json['type'] as int?,
livePlanStartTime: json['live_plan_start_time'] as int?,
lotteryType: json['lottery_type'] as int?,
lotteryId: json['lottery_id'] as String?,
subType: json['sub_type'] as int?,
);
Map<String, dynamic> toJson() => {
'id': id,
'title': title,
'stime': stime,
'etime': etime,
'type': type,
'live_plan_start_time': livePlanStartTime,
'lottery_type': lotteryType,
'lottery_id': lotteryId,
'sub_type': subType,
};
}

View File

@@ -2,17 +2,15 @@ import 'package:PiliPlus/models_new/dynamic/dyn_topic_feed/all_sort_by.dart';
class TopicSortByConf {
List<AllSortBy>? allSortBy;
int? defaultSortBy;
int? showSortBy;
TopicSortByConf({this.allSortBy, this.defaultSortBy, this.showSortBy});
TopicSortByConf({this.allSortBy, this.showSortBy});
factory TopicSortByConf.fromJson(Map<String, dynamic> json) {
return TopicSortByConf(
allSortBy: (json['all_sort_by'] as List<dynamic>?)
?.map((e) => AllSortBy.fromJson(e as Map<String, dynamic>))
.toList(),
defaultSortBy: json['default_sort_by'] as int?,
showSortBy: json['show_sort_by'] as int?,
);
}

View File

@@ -1,32 +1,20 @@
import 'package:PiliPlus/models_new/dynamic/dyn_topic_pub_search/new_topic.dart';
import 'package:PiliPlus/models_new/dynamic/dyn_topic_pub_search/page_info.dart';
import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/topic_item.dart';
class TopicPubSearchData {
NewTopic? newTopic;
bool? hasCreateJurisdiction;
List<TopicItem>? topicItems;
String? requestId;
PageInfo? pageInfo;
TopicPubSearchData({
this.newTopic,
this.hasCreateJurisdiction,
this.topicItems,
this.requestId,
this.pageInfo,
});
factory TopicPubSearchData.fromJson(Map<String, dynamic> json) =>
TopicPubSearchData(
newTopic: json['new_topic'] == null
? null
: NewTopic.fromJson(json['new_topic'] as Map<String, dynamic>),
hasCreateJurisdiction: json['has_create_jurisdiction'] as bool?,
topicItems: (json['topic_items'] as List<dynamic>?)
?.map((e) => TopicItem.fromJson(e as Map<String, dynamic>))
.toList(),
requestId: json['request_id'] as String?,
pageInfo: json['page_info'] == null
? null
: PageInfo.fromJson(json['page_info'] as Map<String, dynamic>),

View File

@@ -1,9 +0,0 @@
class NewTopic {
String? name;
NewTopic({this.name});
factory NewTopic.fromJson(Map<String, dynamic> json) => NewTopic(
name: json['name'] as String?,
);
}

View File

@@ -1,11 +1,9 @@
class PageInfo {
int? offset;
bool? hasMore;
PageInfo({this.offset, this.hasMore});
PageInfo({this.hasMore});
factory PageInfo.fromJson(Map<String, dynamic> json) => PageInfo(
offset: json['offset'] as int?,
hasMore: json['has_more'] as bool?,
);
}

View File

@@ -4,16 +4,10 @@ import 'package:PiliPlus/models_new/dynamic/dyn_topic_top/topic_item.dart';
class TopDetails {
TopicItem? topicItem;
TopicCreator? topicCreator;
bool? hasCreateJurisdiction;
int? wordColor;
bool? closePubLayerEntry;
TopDetails({
this.topicItem,
this.topicCreator,
this.hasCreateJurisdiction,
this.wordColor,
this.closePubLayerEntry,
});
factory TopDetails.fromJson(Map<String, dynamic> json) => TopDetails(
@@ -23,8 +17,5 @@ class TopDetails {
topicCreator: json['topic_creator'] == null
? null
: TopicCreator.fromJson(json['topic_creator'] as Map<String, dynamic>),
hasCreateJurisdiction: json['has_create_jurisdiction'] as bool?,
wordColor: json['word_color'] as int?,
closePubLayerEntry: json['close_pub_layer_entry'] as bool?,
);
}

View File

@@ -5,14 +5,7 @@ class TopicItem {
int discuss;
int fav;
int like;
int? dynamics;
String? jumpUrl;
String? backColor;
String? description;
String? sharePic;
String? shareUrl;
int? ctime;
bool? showInteractData;
bool? isFav;
bool? isLike;
@@ -23,14 +16,7 @@ class TopicItem {
required this.discuss,
required this.fav,
required this.like,
this.dynamics,
this.jumpUrl,
this.backColor,
this.description,
this.sharePic,
this.shareUrl,
this.ctime,
this.showInteractData,
this.isFav,
this.isLike,
});
@@ -42,14 +28,7 @@ class TopicItem {
discuss: json['discuss'] ?? 0,
fav: json['fav'] ?? 0,
like: json['like'] ?? 0,
dynamics: json['dynamics'] as int?,
jumpUrl: json['jump_url'] as String?,
backColor: json['back_color'] as String?,
description: json['description'] as String?,
sharePic: json['share_pic'] as String?,
shareUrl: json['share_url'] as String?,
ctime: json['ctime'] as int?,
showInteractData: json['show_interact_data'] as bool?,
isFav: json['is_fav'] as bool?,
isLike: json['is_like'] as bool?,
);

View File

@@ -1,13 +1,9 @@
class Author {
String? name;
String? face;
String? mid;
Author({this.name, this.face, this.mid});
Author({this.name});
factory Author.fromJson(Map<String, dynamic> json) => Author(
name: json['name'] as String?,
face: json['face'] as String?,
mid: json['mid'] as String?,
);
}

View File

@@ -1,13 +1,9 @@
class Cover {
String? url;
int? width;
int? height;
Cover({this.url, this.width, this.height});
Cover({this.url});
factory Cover.fromJson(Map<String, dynamic> json) => Cover(
url: json['url'] as String?,
width: json['width'] as int?,
height: json['height'] as int?,
);
}

View File

@@ -3,16 +3,10 @@ import 'package:PiliPlus/models_new/fav/fav_article/item.dart';
class FavArticleData {
List<FavArticleItemModel>? items;
bool? hasMore;
String? offset;
String? updateNum;
String? updateBaseline;
FavArticleData({
this.items,
this.hasMore,
this.offset,
this.updateNum,
this.updateBaseline,
});
factory FavArticleData.fromJson(Map<String, dynamic> json) => FavArticleData(
@@ -20,8 +14,5 @@ class FavArticleData {
?.map((e) => FavArticleItemModel.fromJson(e as Map<String, dynamic>))
.toList(),
hasMore: json['has_more'] as bool?,
offset: json['offset'] as String?,
updateNum: json['update_num'] as String?,
updateBaseline: json['update_baseline'] as String?,
);
}

View File

@@ -3,20 +3,16 @@ import 'package:PiliPlus/models_new/fav/fav_article/cover.dart';
import 'package:PiliPlus/models_new/fav/fav_article/stat.dart';
class FavArticleItemModel {
String? jumpUrl;
String? opusId;
String? content;
dynamic badge;
Author? author;
Cover? cover;
Stat? stat;
String? pubTime;
FavArticleItemModel({
this.jumpUrl,
this.opusId,
this.content,
this.badge,
this.author,
this.cover,
this.stat,
@@ -25,10 +21,8 @@ class FavArticleItemModel {
factory FavArticleItemModel.fromJson(Map<String, dynamic> json) =>
FavArticleItemModel(
jumpUrl: json['jump_url'] as String?,
opusId: json['opus_id'] as String?,
content: json['content'] as String?,
badge: json['badge'] as dynamic,
author: json['author'] == null
? null
: Author.fromJson(json['author'] as Map<String, dynamic>),

View File

@@ -1,11 +1,9 @@
class Stat {
String? view;
String? like;
Stat({this.view, this.like});
Stat({this.like});
factory Stat.fromJson(Map<String, dynamic> json) => Stat(
view: json['view'] as String?,
like: json['like'] as String?,
);
}

View File

@@ -1,41 +1,15 @@
class CntInfo {
int? collect;
int? play;
int? thumbUp;
int? thumbDown;
int? share;
int? reply;
int? danmaku;
num? coin;
int? vt;
int? playSwitch;
String? viewText1;
CntInfo({
this.collect,
this.play,
this.thumbUp,
this.thumbDown,
this.share,
this.reply,
this.danmaku,
this.coin,
this.vt,
this.playSwitch,
this.viewText1,
});
factory CntInfo.fromJson(Map<String, dynamic> json) => CntInfo(
collect: json['collect'] as int?,
play: json['play'] as int?,
thumbUp: json['thumb_up'] as int?,
thumbDown: json['thumb_down'] as int?,
share: json['share'] as int?,
reply: json['reply'] as int?,
danmaku: json['danmaku'] as int?,
coin: json['coin'] as num?,
vt: json['vt'] as int?,
playSwitch: json['play_switch'] as int?,
viewText1: json['view_text_1'] as String?,
);
}

View File

@@ -5,9 +5,8 @@ class FavDetailData {
FavFolderInfo? info;
List<FavDetailItemModel>? medias;
bool? hasMore;
int? ttl;
FavDetailData({this.info, this.medias, this.hasMore, this.ttl});
FavDetailData({this.info, this.medias, this.hasMore});
factory FavDetailData.fromJson(Map<String, dynamic> json) => FavDetailData(
info: json['info'] == null
@@ -17,6 +16,5 @@ class FavDetailData {
?.map((e) => FavDetailItemModel.fromJson(e as Map<String, dynamic>))
.toList(),
hasMore: json['has_more'] as bool?,
ttl: json['ttl'] as int?,
);
}

View File

@@ -1,69 +0,0 @@
import 'package:PiliPlus/models/model_owner.dart';
import 'package:PiliPlus/models_new/fav/fav_detail/cnt_info.dart';
class FavDetailInfo {
int? id;
int? fid;
int? mid;
int? attr;
String? title;
String? cover;
Owner? upper;
int? coverType;
CntInfo? cntInfo;
int? type;
String? intro;
int? ctime;
int? mtime;
int? state;
int? favState;
int? likeState;
int? mediaCount;
bool? isTop;
FavDetailInfo({
this.id,
this.fid,
this.mid,
this.attr,
this.title,
this.cover,
this.upper,
this.coverType,
this.cntInfo,
this.type,
this.intro,
this.ctime,
this.mtime,
this.state,
this.favState,
this.likeState,
this.mediaCount,
this.isTop,
});
factory FavDetailInfo.fromJson(Map<String, dynamic> json) => FavDetailInfo(
id: json['id'] as int?,
fid: json['fid'] as int?,
mid: json['mid'] as int?,
attr: json['attr'] as int?,
title: json['title'] as String?,
cover: json['cover'] as String?,
upper: json['upper'] == null
? null
: Owner.fromJson(json['upper'] as Map<String, dynamic>),
coverType: json['cover_type'] as int?,
cntInfo: json['cnt_info'] == null
? null
: CntInfo.fromJson(json['cnt_info'] as Map<String, dynamic>),
type: json['type'] as int?,
intro: json['intro'] as String?,
ctime: json['ctime'] as int?,
mtime: json['mtime'] as int?,
state: json['state'] as int?,
favState: json['fav_state'] as int?,
likeState: json['like_state'] as int?,
mediaCount: json['media_count'] as int?,
isTop: json['is_top'] as bool?,
);
}

View File

@@ -10,19 +10,14 @@ class FavDetailItemModel with MultiSelectData {
String? title;
String? cover;
String? intro;
int? page;
int? duration;
Owner? upper;
int? attr;
CntInfo? cntInfo;
String? link;
int? ctime;
int? pubtime;
int? favTime;
String? bvid;
Ogv? ogv;
Ugc? ugc;
String? mediaListLink;
FavDetailItemModel({
this.id,
@@ -30,19 +25,14 @@ class FavDetailItemModel with MultiSelectData {
this.title,
this.cover,
this.intro,
this.page,
this.duration,
this.upper,
this.attr,
this.cntInfo,
this.link,
this.ctime,
this.pubtime,
this.favTime,
this.bvid,
this.ogv,
this.ugc,
this.mediaListLink,
});
factory FavDetailItemModel.fromJson(Map<String, dynamic> json) =>
@@ -52,7 +42,6 @@ class FavDetailItemModel with MultiSelectData {
title: json['title'] as String?,
cover: json['cover'] as String?,
intro: json['intro'] as String?,
page: json['page'] as int?,
duration: json['duration'] as int?,
upper: json['upper'] == null
? null
@@ -61,15 +50,11 @@ class FavDetailItemModel with MultiSelectData {
cntInfo: json['cnt_info'] == null
? null
: CntInfo.fromJson(json['cnt_info'] as Map<String, dynamic>),
link: json['link'] as String?,
ctime: json['ctime'] as int?,
pubtime: json['pubtime'] as int?,
favTime: json['fav_time'] as int?,
bvid: json['bvid'] ?? json['bv_id'],
ogv: json['ogv'] == null ? null : Ogv.fromJson(json['ogv']),
ugc: json['ugc'] == null
? null
: Ugc.fromJson(json['ugc'] as Map<String, dynamic>),
mediaListLink: json['media_list_link'] as String?,
);
}

View File

@@ -1,17 +1,14 @@
class Ogv {
String? typeName;
int? typeId;
int? seasonId;
Ogv({
this.typeName,
this.typeId,
this.seasonId,
});
factory Ogv.fromJson(Map<String, dynamic> json) => Ogv(
typeName: json['type_name'],
typeId: json['type_id'],
seasonId: json['season_id'],
);
}

View File

@@ -5,42 +5,24 @@ class FavFolderInfo {
int? fid;
int mid;
int attr;
String? attrDesc;
String title;
String cover;
Owner? upper;
int? coverType;
String? intro;
int? ctime;
int? mtime;
int? state;
int? favState;
int mediaCount;
int? viewCount;
bool? isTop;
int? type;
String? bvid;
FavFolderInfo({
this.id = 0,
this.fid,
this.mid = 0,
this.attr = -1,
this.attrDesc,
this.title = '',
this.cover = '',
this.upper,
this.coverType,
this.intro,
this.ctime,
this.mtime,
this.state,
this.favState,
this.mediaCount = 0,
this.viewCount,
this.isTop,
this.type,
this.bvid,
});
factory FavFolderInfo.fromJson(Map<String, dynamic> json) => FavFolderInfo(
@@ -48,22 +30,13 @@ class FavFolderInfo {
fid: json['fid'] as int?,
mid: json['mid'] as int? ?? 0,
attr: json['attr'] as int? ?? 0,
attrDesc: json['attr_desc'] as String?,
title: json['title'] as String? ?? '',
cover: json['cover'] as String? ?? '',
upper: json['upper'] == null
? null
: Owner.fromJson(json['upper'] as Map<String, dynamic>),
coverType: json['cover_type'] as int?,
intro: json['intro'] as String?,
ctime: json['ctime'] as int?,
mtime: json['mtime'] as int?,
state: json['state'] as int?,
favState: json['fav_state'] as int?,
mediaCount: json['media_count'] as int? ?? 0,
viewCount: json['view_count'] as int?,
isTop: json['is_top'] as bool?,
type: json['type'] as int?,
bvid: json['bvid'] as String?,
);
}

View File

@@ -1,29 +0,0 @@
class Arc {
int? oid;
String? bvid;
String? pic;
String? desc;
int? status;
int? oidType;
int? aid;
Arc({
this.oid,
this.bvid,
this.pic,
this.desc,
this.status,
this.oidType,
this.aid,
});
factory Arc.fromJson(Map<String, dynamic> json) => Arc(
oid: json['oid'] as int?,
bvid: json['bvid'] as String?,
pic: json['pic'] as String?,
desc: json['desc'] as String?,
status: json['status'] as int?,
oidType: json['oid_type'] as int?,
aid: json['aid'] as int?,
);
}

View File

@@ -1,18 +1,13 @@
import 'package:PiliPlus/models_new/fav/fav_note/list.dart';
import 'package:PiliPlus/models_new/fav/fav_note/page.dart';
class FavNoteData {
List<FavNoteItemModel>? list;
Page? page;
FavNoteData({this.list, this.page});
FavNoteData({this.list});
factory FavNoteData.fromJson(Map<String, dynamic> json) => FavNoteData(
list: (json['list'] as List<dynamic>?)
?.map((e) => FavNoteItemModel.fromJson(e as Map<String, dynamic>))
.toList(),
page: json['page'] == null
? null
: Page.fromJson(json['page'] as Map<String, dynamic>),
);
}

View File

@@ -1,13 +0,0 @@
class Page {
int? total;
int? size;
int? num;
Page({this.total, this.size, this.num});
factory Page.fromJson(Map<String, dynamic> json) => Page(
total: json['total'] as int?,
size: json['size'] as int?,
num: json['num'] as int?,
);
}

View File

@@ -1,11 +0,0 @@
class Area {
int? id;
String? name;
Area({this.id, this.name});
factory Area.fromJson(Map<String, dynamic> json) => Area(
id: json['id'] as int?,
name: json['name'] as String?,
);
}

View File

@@ -1,27 +0,0 @@
import 'package:PiliPlus/models_new/fav/fav_pgc/multi_img.dart';
class BadgeInfo {
String? text;
String? bgColor;
String? bgColorNight;
String? img;
MultiImg? multiImg;
BadgeInfo({
this.text,
this.bgColor,
this.bgColorNight,
this.img,
this.multiImg,
});
factory BadgeInfo.fromJson(Map<String, dynamic> json) => BadgeInfo(
text: json['text'] as String?,
bgColor: json['bg_color'] as String?,
bgColorNight: json['bg_color_night'] as String?,
img: json['img'] as String?,
multiImg: json['multi_img'] == null
? null
: MultiImg.fromJson(json['multi_img'] as Map<String, dynamic>),
);
}

View File

@@ -1,18 +0,0 @@
import 'package:PiliPlus/models_new/fav/fav_pgc/content_attr.dart';
import 'package:PiliPlus/models_new/fav/fav_pgc/vip_or_pay.dart';
class BadgeInfos {
ContentAttr? contentAttr;
VipOrPay? vipOrPay;
BadgeInfos({this.contentAttr, this.vipOrPay});
factory BadgeInfos.fromJson(Map<String, dynamic> json) => BadgeInfos(
contentAttr: json['content_attr'] == null
? null
: ContentAttr.fromJson(json['content_attr'] as Map<String, dynamic>),
vipOrPay: json['vip_or_pay'] == null
? null
: VipOrPay.fromJson(json['vip_or_pay'] as Map<String, dynamic>),
);
}

View File

@@ -1,9 +0,0 @@
class CcOnLock {
String? typeUrl;
CcOnLock({this.typeUrl});
factory CcOnLock.fromJson(Map<String, dynamic> json) => CcOnLock(
typeUrl: json['type_url'] as String?,
);
}

Some files were not shown because too many files have changed in this diff Show More