show user medal

Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-03-22 15:01:30 +08:00
parent fc7fc18b14
commit 2bebf200df
151 changed files with 1435 additions and 1321 deletions

View File

@@ -1,4 +1,4 @@
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/style.dart';
import 'package:flutter/material.dart';
class ColorPalette extends StatelessWidget {
@@ -62,7 +62,7 @@ class ColorPalette extends StatelessWidget {
padding: const EdgeInsets.all(6),
decoration: BoxDecoration(
color: colorScheme.onInverseSurface,
borderRadius: StyleString.mdRadius,
borderRadius: Style.mdRadius,
),
child: child,
);

View File

@@ -2,7 +2,7 @@ import 'dart:async' show FutureOr;
import 'dart:convert' show utf8, jsonDecode;
import 'dart:io' show File;
import 'package:PiliPlus/common/constants.dart' show StyleString;
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/utils/extension/context_ext.dart';
import 'package:PiliPlus/utils/utils.dart';
import 'package:file_picker/file_picker.dart';
@@ -155,7 +155,7 @@ void importFromInput<T>(
context: context,
builder: (context) => AlertDialog(
title: Text('输入$title'),
constraints: StyleString.dialogFixedConstraints,
constraints: Style.dialogFixedConstraints,
content: TextFormField(
key: key,
minLines: 4,

View File

@@ -1,4 +1,4 @@
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/http/user.dart';
@@ -22,10 +22,10 @@ void imageSaveDialog({
final theme = Theme.of(context);
return Container(
width: imgWidth,
margin: const .symmetric(horizontal: StyleString.safeSpace),
margin: const .symmetric(horizontal: Style.safeSpace),
decoration: BoxDecoration(
color: theme.colorScheme.surface,
borderRadius: StyleString.mdRadius,
borderRadius: Style.mdRadius,
),
child: Column(
mainAxisSize: MainAxisSize.min,
@@ -39,8 +39,8 @@ void imageSaveDialog({
src: cover,
quality: 100,
width: imgWidth,
height: imgWidth / StyleString.aspectRatio16x9,
borderRadius: const .vertical(top: StyleString.imgRadius),
height: imgWidth / Style.aspectRatio16x9,
borderRadius: const .vertical(top: Style.imgRadius),
),
),
Positioned(

View File

@@ -1,4 +1,5 @@
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/assets.dart';
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/models/common/image_type.dart';
import 'package:PiliPlus/utils/extension/num_ext.dart';
import 'package:PiliPlus/utils/image_utils.dart';
@@ -16,7 +17,7 @@ class NetworkImgLayer extends StatelessWidget {
this.fadeOutDuration = const Duration(milliseconds: 120),
this.fadeInDuration = const Duration(milliseconds: 120),
this.quality = 1,
this.borderRadius = StyleString.mdRadius,
this.borderRadius = Style.mdRadius,
this.getPlaceHolder,
this.fit = .cover,
this.alignment = .center,
@@ -108,7 +109,7 @@ class NetworkImgLayer extends StatelessWidget {
),
child: Center(
child: Image.asset(
isAvatar ? 'assets/images/noface.jpeg' : 'assets/images/loading.png',
isAvatar ? Assets.avatarPlaceHolder : Assets.loading,
width: width,
height: height,
cacheWidth: width.cacheSize(context),

View File

@@ -18,7 +18,7 @@
import 'dart:collection' show HashSet;
import 'dart:math' as math;
import 'package:PiliPlus/common/constants.dart' show StyleString;
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/image_grid/image_grid_view.dart'
show ImageModel;
import 'package:flutter/foundation.dart' show kDebugMode;
@@ -505,7 +505,7 @@ class ImageGridRenderObjectElement extends RenderObjectElement {
if (width != 1) {
imageWidth = math.min(imageWidth, width.toDouble());
}
imageHeight = imageWidth * math.min(ratioHW, StyleString.imgMaxRatio);
imageHeight = imageWidth * math.min(ratioHW, Style.imgMaxRatio);
}
}

View File

@@ -17,7 +17,8 @@
import 'dart:io' show Platform;
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/assets.dart';
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/badge.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/common/widgets/image_grid/image_grid_builder.dart';
@@ -53,8 +54,7 @@ class ImageModel {
bool? _isLongPic;
bool? _isLivePhoto;
bool get isLongPic =>
_isLongPic ??= (height / width) > StyleString.imgMaxRatio;
bool get isLongPic => _isLongPic ??= (height / width) > Style.imgMaxRatio;
bool get isLivePhoto =>
_isLivePhoto ??= enableLivePhoto && liveUrl?.isNotEmpty == true;
@@ -116,9 +116,9 @@ class ImageGridView extends StatelessWidget {
int col,
int length,
int index, {
Radius r = StyleString.imgRadius,
Radius r = Style.imgRadius,
}) {
if (length == 1) return StyleString.mdRadius;
if (length == 1) return Style.mdRadius;
final bool hasUp = index - col >= 0;
final bool hasDown = index + col < length;
@@ -213,7 +213,7 @@ class ImageGridView extends StatelessWidget {
).colorScheme.onInverseSurface.withValues(alpha: 0.4),
),
child: Image.asset(
'assets/images/loading.png',
Assets.loading,
width: width,
height: height,
cacheWidth: width.cacheSize(context),

View File

@@ -5,7 +5,7 @@
import 'dart:io' show File;
import 'dart:math' as math;
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/gesture/image_horizontal_drag_gesture_recognizer.dart';
import 'package:PiliPlus/common/widgets/image_viewer/viewer.dart';
import 'package:flutter/foundation.dart';
@@ -603,7 +603,7 @@ class _ImageState extends State<Image> with WidgetsBindingObserver {
final imgHeight = _imageInfo!.image.height.toDouble();
final imgRatio = imgHeight / imgWidth;
isLongPic =
imgRatio > StyleString.imgMaxRatio &&
imgRatio > Style.imgMaxRatio &&
imgHeight > widget.containerSize.height;
if (isLongPic) {
final compatWidth = math.min(650.0, widget.containerSize.width);

View File

@@ -1,77 +1,87 @@
import 'package:PiliPlus/common/assets.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/models/common/avatar_badge_type.dart';
import 'package:PiliPlus/models/common/image_type.dart';
import 'package:PiliPlus/utils/extension/num_ext.dart';
import 'package:PiliPlus/utils/extension/string_ext.dart';
import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/storage_pref.dart';
import 'package:flutter/material.dart';
class PendantAvatar extends StatelessWidget {
final BadgeType _badgeType;
final String? avatar;
final double size;
final double badgeSize;
final String? garbPendantImage;
final int? roomId;
final VoidCallback? onTap;
final bool isMemberAvatar;
const PendantAvatar({
const PendantAvatar(
this.url, {
super.key,
required this.avatar,
required this.size,
this.isMemberAvatar = false,
required double size,
double? badgeSize,
bool isVip = false,
int? vipStatus,
int? officialType,
this.garbPendantImage,
this.pendantImage,
this.pendentOffset = 6,
this.roomId,
this.onTap,
}) : _badgeType = officialType == null || officialType < 0
? isVip
? BadgeType.vip
: BadgeType.none
}) : preferredSize = size,
badgeSize = badgeSize ?? size / 3,
badgeType = officialType == null || officialType < 0
? vipStatus != null && vipStatus > 0
? .vip
: .none
: officialType == 0
? BadgeType.person
? .person
: officialType == 1
? BadgeType.institution
: BadgeType.none,
badgeSize = badgeSize ?? size / 3;
? .institution
: .none;
static bool showDynDecorate = Pref.showDynDecorate;
final BadgeType badgeType;
final String? url;
final double preferredSize;
final double badgeSize;
final String? pendantImage;
final double pendentOffset;
final int? roomId;
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
final showPendant = showDynDecorate && pendantImage?.isNotEmpty == true;
final size = showPendant ? preferredSize - pendentOffset : preferredSize;
Widget? pendant;
if (showDynDecorate && !garbPendantImage.isNullOrEmpty) {
if (showPendant) {
final pendantSize = size * 1.75;
pendant = Positioned(
// -(size * 1.75 - size) / 2
top: -0.375 * size + (isMemberAvatar ? 2 : 0),
top: -0.375 * size + pendentOffset,
child: IgnorePointer(
child: NetworkImgLayer(
type: .emote,
width: pendantSize,
height: pendantSize,
src: garbPendantImage,
src: pendantImage,
getPlaceHolder: () => const SizedBox.shrink(),
),
),
);
}
return Stack(
alignment: Alignment.bottomCenter,
clipBehavior: Clip.none,
Widget avatar = NetworkImgLayer(
src: url,
width: size,
height: size,
type: ImageType.avatar,
);
if (onTap != null) {
avatar = GestureDetector(
behavior: .opaque,
onTap: onTap,
child: avatar,
);
}
Widget child = Stack(
clipBehavior: .none,
alignment: .center,
children: [
onTap == null
? _buildAvatar(colorScheme, isMemberAvatar)
: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: onTap,
child: _buildAvatar(colorScheme, isMemberAvatar),
),
avatar,
?pendant,
if (roomId != null)
Positioned(
@@ -106,63 +116,38 @@ class PendantAvatar extends StatelessWidget {
),
),
)
else if (_badgeType != BadgeType.none)
_buildBadge(context, colorScheme, isMemberAvatar),
else if (badgeType != BadgeType.none)
_buildBadge(context, colorScheme),
],
);
if (showPendant) {
return SizedBox.square(
dimension: preferredSize,
child: child,
);
}
return child;
}
Widget _buildAvatar(ColorScheme colorScheme, bool isMemberAvatar) =>
isMemberAvatar
? DecoratedBox(
decoration: BoxDecoration(
border: Border.all(
width: 2,
color: colorScheme.surface,
),
shape: BoxShape.circle,
),
child: Padding(
padding: const EdgeInsets.all(2),
child: NetworkImgLayer(
src: avatar,
width: size,
height: size,
type: ImageType.avatar,
),
),
)
: NetworkImgLayer(
src: avatar,
width: size,
height: size,
type: ImageType.avatar,
);
Widget _buildBadge(
BuildContext context,
ColorScheme colorScheme,
bool isMemberAvatar,
) {
final child = switch (_badgeType) {
Widget _buildBadge(BuildContext context, ColorScheme colorScheme) {
final child = switch (badgeType) {
BadgeType.vip => Image.asset(
'assets/images/big-vip.png',
Assets.vipIcon,
width: badgeSize,
height: badgeSize,
cacheWidth: badgeSize.cacheSize(context),
semanticLabel: _badgeType.desc,
semanticLabel: badgeType.desc,
),
_ => Icon(
Icons.offline_bolt,
color: _badgeType.color,
color: badgeType.color,
size: badgeSize,
semanticLabel: _badgeType.desc,
semanticLabel: badgeType.desc,
),
};
final offset = isMemberAvatar ? 2.0 : 0.0;
return Positioned(
right: offset,
bottom: offset,
right: 0.0,
bottom: 0.0,
child: IgnorePointer(
child: DecoratedBox(
decoration: BoxDecoration(

View File

@@ -1,10 +1,10 @@
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/style.dart';
import 'package:flutter/material.dart';
Widget selectMask(
ThemeData theme,
bool checked, {
BorderRadiusGeometry borderRadius = StyleString.mdRadius,
BorderRadiusGeometry borderRadius = Style.mdRadius,
}) {
return AnimatedOpacity(
opacity: checked ? 1 : 0,

View File

@@ -1,4 +1,4 @@
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/badge.dart';
import 'package:PiliPlus/common/widgets/flutter/layout_builder.dart';
import 'package:PiliPlus/common/widgets/image/image_save.dart';
@@ -120,14 +120,14 @@ class VideoCardH extends StatelessWidget {
},
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: StyleString.safeSpace,
horizontal: Style.safeSpace,
vertical: 5,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: StyleString.aspectRatio,
aspectRatio: Style.aspectRatio,
child: LayoutBuilder(
builder: (context, boxConstraints) {
final double maxWidth = boxConstraints.maxWidth;

View File

@@ -1,4 +1,4 @@
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/style.dart';
import 'package:PiliPlus/common/widgets/badge.dart';
import 'package:PiliPlus/common/widgets/flutter/layout_builder.dart';
import 'package:PiliPlus/common/widgets/image/image_save.dart';
@@ -87,7 +87,7 @@ class VideoCardV extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AspectRatio(
aspectRatio: StyleString.aspectRatio,
aspectRatio: Style.aspectRatio,
child: LayoutBuilder(
builder: (context, boxConstraints) {
double maxWidth = boxConstraints.maxWidth;