Merge branch 'test' into feature
This commit is contained in:
commit
671f925232
@ -587,7 +587,11 @@ class _PersonDetailPageState extends State<PersonDetailPage> {
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
SCDataCardResourceView(resource: dataCard, fit: BoxFit.cover),
|
||||
SCDataCardResourceView(
|
||||
resource: dataCard,
|
||||
fit: BoxFit.cover,
|
||||
fallback: DecoratedBox(decoration: _defaultDataCardDecoration()),
|
||||
),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
@ -606,6 +610,21 @@ class _PersonDetailPageState extends State<PersonDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
BoxDecoration _defaultDataCardDecoration() {
|
||||
return const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Color(0xff18F2B1),
|
||||
Color(0xffE4FFF6),
|
||||
Color(0xffF7FFFC),
|
||||
Color(0xffFFFFFF),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
PropsResources? _activeDataCard(SocialChatUserProfile? profile) {
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
for (final item in profile?.useProps ?? const <UseProps>[]) {
|
||||
|
||||
@ -13,6 +13,7 @@ import 'package:yumi/shared/tools/sc_loading_manager.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_compontent.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_debounce_widget.dart';
|
||||
import 'package:yumi/ui_kit/components/sc_tts.dart';
|
||||
import 'package:yumi/ui_kit/widgets/props/sc_data_card_resource_view.dart';
|
||||
|
||||
class VipDetailPage extends StatefulWidget {
|
||||
const VipDetailPage({super.key});
|
||||
@ -58,7 +59,6 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
final status = results[1] as SCVipStatusRes;
|
||||
final resolvedStatus = _resolveStatus(status, home.state);
|
||||
final selectedLevel = _resolveInitialLevel(home, resolvedStatus);
|
||||
_logLoadedVipData(home, resolvedStatus, selectedLevel);
|
||||
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
@ -141,11 +141,6 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
_selectedLevel = level;
|
||||
_preview = null;
|
||||
});
|
||||
_logSelectedLevelResources(
|
||||
level,
|
||||
config: _levelConfigFor(level),
|
||||
status: _status,
|
||||
);
|
||||
_loadPreviewForLevel(level);
|
||||
}
|
||||
|
||||
@ -201,6 +196,7 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
await _loadVipData(showLoading: false);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint('VIP purchase failed: $error');
|
||||
} finally {
|
||||
SCLoadingManager.hide();
|
||||
if (mounted) {
|
||||
@ -214,56 +210,6 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
return 'vip-buy-$userId-${DateTime.now().millisecondsSinceEpoch}';
|
||||
}
|
||||
|
||||
void _logLoadedVipData(
|
||||
SCVipHomeRes home,
|
||||
SCVipStatusRes? status,
|
||||
int selectedLevel,
|
||||
) {
|
||||
if (home.configured != true) {}
|
||||
if (home.levels.isEmpty) {}
|
||||
_logSelectedLevelResources(
|
||||
selectedLevel,
|
||||
config: _levelConfigFromHome(home, selectedLevel),
|
||||
status: status,
|
||||
);
|
||||
}
|
||||
|
||||
void _logSelectedLevelResources(
|
||||
int level, {
|
||||
required SCVipLevelConfigRes? config,
|
||||
required SCVipStatusRes? status,
|
||||
}) {
|
||||
final state = status?.levelInt == level ? status : null;
|
||||
if (config == null && state == null) {
|
||||
return;
|
||||
}
|
||||
final badge = _preferResource(config?.badge, state?.badge);
|
||||
final avatarFrame = _preferResource(
|
||||
config?.avatarFrame,
|
||||
state?.avatarFrame,
|
||||
);
|
||||
final entryEffect = _preferResource(
|
||||
config?.entryEffect,
|
||||
state?.entryEffect,
|
||||
);
|
||||
final chatBubble = _preferResource(config?.chatBubble, state?.chatBubble);
|
||||
final floatPicture = _preferResource(
|
||||
config?.floatPicture,
|
||||
state?.floatPicture,
|
||||
);
|
||||
}
|
||||
|
||||
String _resourceLogValue(SCVipResourceRes? resource) {
|
||||
if (!_hasResource(resource)) {
|
||||
return 'null';
|
||||
}
|
||||
return '{id:${resource?.resourceId},name:${resource?.name},'
|
||||
'hasPreviewUrl:${resource?.hasPreviewUrl},'
|
||||
'hasSourceUrl:${resource?.hasSourceUrl},'
|
||||
'previewUrl:${resource?.previewUrl},'
|
||||
'sourceUrl:${resource?.sourceResourceUrl}}';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -524,6 +470,8 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
|
||||
Widget _buildLevelCard() {
|
||||
final assetLevel = _assetLevel;
|
||||
final backgroundCard = _selectedBackgroundCard;
|
||||
final effectImage = _selectedEffectImage ?? _selectedLongBadge;
|
||||
return Center(
|
||||
child: SizedBox(
|
||||
width: 351.w,
|
||||
@ -532,18 +480,23 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.w),
|
||||
border: Border.all(
|
||||
color: const Color(0xFFEBCB76),
|
||||
width: 1.w,
|
||||
),
|
||||
image: DecorationImage(
|
||||
image: AssetImage(
|
||||
'sc_images/vip/sc_vip_card_bg_$assetLevel.png',
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8.w),
|
||||
child: _buildVipCardBackground(
|
||||
resource: backgroundCard,
|
||||
assetLevel: assetLevel,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: IgnorePointer(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(8.w),
|
||||
border: Border.all(
|
||||
color: const Color(0xFFEBCB76),
|
||||
width: 1.w,
|
||||
),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -575,8 +528,8 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
PositionedDirectional(
|
||||
end: 24.w,
|
||||
top: -36.w,
|
||||
child: _buildResourceImage(
|
||||
resource: _selectedBadge,
|
||||
child: _buildDynamicResourceVisual(
|
||||
resource: effectImage,
|
||||
width: 135.w,
|
||||
height: 135.w,
|
||||
fallbackIcon: Icons.workspace_premium_outlined,
|
||||
@ -588,6 +541,27 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildVipCardBackground({
|
||||
required SCVipResourceRes? resource,
|
||||
required int assetLevel,
|
||||
}) {
|
||||
final fallback = Image.asset(
|
||||
'sc_images/vip/sc_vip_card_bg_$assetLevel.png',
|
||||
fit: BoxFit.fill,
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
);
|
||||
if (!_hasResourceUrl(resource)) {
|
||||
return fallback;
|
||||
}
|
||||
return SCDataCardResourceView(
|
||||
sourceUrl: resource?.sourceResourceUrl,
|
||||
coverUrl: resource?.previewUrl,
|
||||
fit: BoxFit.fill,
|
||||
fallback: fallback,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLevelDivider() {
|
||||
final ornamentLayout = _ornamentLayoutForLevel(_assetLevel);
|
||||
return SizedBox(
|
||||
@ -713,9 +687,14 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
);
|
||||
}
|
||||
|
||||
SCVipResourceRes? get _selectedBadge => _selectedResource(
|
||||
fromConfig: (config) => config.badge,
|
||||
fromState: (status) => status.badge,
|
||||
SCVipResourceRes? get _selectedLongBadge => _selectedResource(
|
||||
fromConfig: (config) => config.longBadge,
|
||||
fromState: (status) => status.longBadge,
|
||||
);
|
||||
|
||||
SCVipResourceRes? get _selectedShortBadge => _selectedResource(
|
||||
fromConfig: (config) => config.shortBadge,
|
||||
fromState: (status) => status.shortBadge,
|
||||
);
|
||||
|
||||
SCVipResourceRes? get _selectedAvatarFrame => _selectedResource(
|
||||
@ -738,6 +717,16 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
fromState: (status) => status.floatPicture,
|
||||
);
|
||||
|
||||
SCVipResourceRes? get _selectedBackgroundCard => _selectedResource(
|
||||
fromConfig: (config) => config.backgroundCard,
|
||||
fromState: (status) => status.backgroundCard,
|
||||
);
|
||||
|
||||
SCVipResourceRes? get _selectedEffectImage => _selectedResource(
|
||||
fromConfig: (config) => config.effectImage,
|
||||
fromState: (status) => status.effectImage,
|
||||
);
|
||||
|
||||
SCVipResourceRes? _selectedResource({
|
||||
required SCVipResourceRes? Function(SCVipLevelConfigRes config) fromConfig,
|
||||
required SCVipResourceRes? Function(SCVipStatusRes status) fromState,
|
||||
@ -768,8 +757,14 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
final items = <_VipFeatureData>[];
|
||||
_addResourceItem(
|
||||
items,
|
||||
resource: _selectedBadge,
|
||||
fallbackTitle: 'VIP Badge',
|
||||
resource: _selectedLongBadge,
|
||||
fallbackTitle: 'Long Badge',
|
||||
fallbackIcon: Icons.workspace_premium_outlined,
|
||||
);
|
||||
_addResourceItem(
|
||||
items,
|
||||
resource: _selectedShortBadge,
|
||||
fallbackTitle: 'Short Badge',
|
||||
fallbackIcon: Icons.workspace_premium_outlined,
|
||||
);
|
||||
_addResourceItem(
|
||||
@ -797,12 +792,19 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
fallbackIcon: Icons.airline_seat_recline_extra,
|
||||
wide: true,
|
||||
);
|
||||
_addResourceItem(
|
||||
items,
|
||||
resource: _selectedBackgroundCard,
|
||||
fallbackTitle: 'Profile Card',
|
||||
fallbackIcon: Icons.badge_outlined,
|
||||
wide: true,
|
||||
);
|
||||
return items;
|
||||
}
|
||||
|
||||
List<_VipFeatureData> get _vipPrivilegeItems {
|
||||
// The VIP home API currently returns resource perks only:
|
||||
// badge/avatarFrame/entryEffect/chatBubble/floatPicture.
|
||||
// badges/avatarFrame/entryEffect/chatBubble/floatPicture/backgroundCard.
|
||||
// Do not render demo-only functional privileges without backend data.
|
||||
return const <_VipFeatureData>[];
|
||||
}
|
||||
@ -844,6 +846,40 @@ class _VipDetailPageState extends State<VipDetailPage> {
|
||||
return fallbackTitle;
|
||||
}
|
||||
|
||||
Widget _buildDynamicResourceVisual({
|
||||
required SCVipResourceRes? resource,
|
||||
required double width,
|
||||
required double height,
|
||||
required IconData fallbackIcon,
|
||||
}) {
|
||||
final sourceUrl = resource?.sourceResourceUrl?.trim();
|
||||
final previewUrl = resource?.previewUrl?.trim();
|
||||
final hasSource = sourceUrl != null && sourceUrl.isNotEmpty;
|
||||
final hasPreview = previewUrl != null && previewUrl.isNotEmpty;
|
||||
if (hasSource || hasPreview) {
|
||||
return SCDataCardResourceView(
|
||||
sourceUrl: sourceUrl,
|
||||
coverUrl: previewUrl,
|
||||
width: width,
|
||||
height: height,
|
||||
fit: BoxFit.contain,
|
||||
fallback: _buildResourceImage(
|
||||
resource: resource,
|
||||
width: width,
|
||||
height: height,
|
||||
fallbackIcon: fallbackIcon,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return _buildResourceImage(
|
||||
resource: resource,
|
||||
width: width,
|
||||
height: height,
|
||||
fallbackIcon: fallbackIcon,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildResourceImage({
|
||||
required SCVipResourceRes? resource,
|
||||
required double width,
|
||||
|
||||
@ -110,10 +110,14 @@ class SCVipStatusRes {
|
||||
String? startAt,
|
||||
String? expireAt,
|
||||
SCVipResourceRes? badge,
|
||||
SCVipResourceRes? longBadge,
|
||||
SCVipResourceRes? shortBadge,
|
||||
SCVipResourceRes? avatarFrame,
|
||||
SCVipResourceRes? entryEffect,
|
||||
SCVipResourceRes? chatBubble,
|
||||
SCVipResourceRes? floatPicture,
|
||||
SCVipResourceRes? backgroundCard,
|
||||
SCVipResourceRes? effectImage,
|
||||
}) {
|
||||
_userId = userId;
|
||||
_sysOrigin = sysOrigin;
|
||||
@ -125,10 +129,14 @@ class SCVipStatusRes {
|
||||
_startAt = startAt;
|
||||
_expireAt = expireAt;
|
||||
_badge = badge;
|
||||
_longBadge = longBadge;
|
||||
_shortBadge = shortBadge;
|
||||
_avatarFrame = avatarFrame;
|
||||
_entryEffect = entryEffect;
|
||||
_chatBubble = chatBubble;
|
||||
_floatPicture = floatPicture;
|
||||
_backgroundCard = backgroundCard;
|
||||
_effectImage = effectImage;
|
||||
}
|
||||
|
||||
SCVipStatusRes.fromJson(dynamic json) {
|
||||
@ -144,10 +152,14 @@ class SCVipStatusRes {
|
||||
_startAt = _stringValue(map['startAt']);
|
||||
_expireAt = _stringValue(map['expireAt']);
|
||||
_badge = _resourceValue(map['badge']);
|
||||
_longBadge = _resourceValue(map['longBadge']) ?? _badge;
|
||||
_shortBadge = _resourceValue(map['shortBadge']);
|
||||
_avatarFrame = _resourceValue(map['avatarFrame']);
|
||||
_entryEffect = _resourceValue(map['entryEffect']);
|
||||
_chatBubble = _resourceValue(map['chatBubble']);
|
||||
_floatPicture = _resourceValue(map['floatPicture']);
|
||||
_backgroundCard = _resourceValue(map['backgroundCard']);
|
||||
_effectImage = _resourceValue(map['effectImage']);
|
||||
}
|
||||
|
||||
String? _userId;
|
||||
@ -160,10 +172,14 @@ class SCVipStatusRes {
|
||||
String? _startAt;
|
||||
String? _expireAt;
|
||||
SCVipResourceRes? _badge;
|
||||
SCVipResourceRes? _longBadge;
|
||||
SCVipResourceRes? _shortBadge;
|
||||
SCVipResourceRes? _avatarFrame;
|
||||
SCVipResourceRes? _entryEffect;
|
||||
SCVipResourceRes? _chatBubble;
|
||||
SCVipResourceRes? _floatPicture;
|
||||
SCVipResourceRes? _backgroundCard;
|
||||
SCVipResourceRes? _effectImage;
|
||||
|
||||
String? get userId => _userId;
|
||||
|
||||
@ -183,7 +199,11 @@ class SCVipStatusRes {
|
||||
|
||||
String? get expireAt => _expireAt;
|
||||
|
||||
SCVipResourceRes? get badge => _badge;
|
||||
SCVipResourceRes? get badge => longBadge;
|
||||
|
||||
SCVipResourceRes? get longBadge => _longBadge ?? _badge;
|
||||
|
||||
SCVipResourceRes? get shortBadge => _shortBadge;
|
||||
|
||||
SCVipResourceRes? get avatarFrame => _avatarFrame;
|
||||
|
||||
@ -193,6 +213,10 @@ class SCVipStatusRes {
|
||||
|
||||
SCVipResourceRes? get floatPicture => _floatPicture;
|
||||
|
||||
SCVipResourceRes? get backgroundCard => _backgroundCard;
|
||||
|
||||
SCVipResourceRes? get effectImage => _effectImage;
|
||||
|
||||
bool get isActive => _active == true && (_level ?? 0) > 0;
|
||||
|
||||
int get levelInt => (_level ?? 0).toInt();
|
||||
@ -216,11 +240,17 @@ class SCVipStatusRes {
|
||||
map['displayName'] = _displayName;
|
||||
map['startAt'] = _startAt;
|
||||
map['expireAt'] = _expireAt;
|
||||
if (_badge != null) map['badge'] = _badge?.toJson();
|
||||
if (badge != null) map['badge'] = badge?.toJson();
|
||||
if (longBadge != null) map['longBadge'] = longBadge?.toJson();
|
||||
if (_shortBadge != null) map['shortBadge'] = _shortBadge?.toJson();
|
||||
if (_avatarFrame != null) map['avatarFrame'] = _avatarFrame?.toJson();
|
||||
if (_entryEffect != null) map['entryEffect'] = _entryEffect?.toJson();
|
||||
if (_chatBubble != null) map['chatBubble'] = _chatBubble?.toJson();
|
||||
if (_floatPicture != null) map['floatPicture'] = _floatPicture?.toJson();
|
||||
if (_backgroundCard != null) {
|
||||
map['backgroundCard'] = _backgroundCard?.toJson();
|
||||
}
|
||||
if (_effectImage != null) map['effectImage'] = _effectImage?.toJson();
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@ -234,10 +264,14 @@ class SCVipLevelConfigRes {
|
||||
num? durationDays,
|
||||
num? priceGold,
|
||||
SCVipResourceRes? badge,
|
||||
SCVipResourceRes? longBadge,
|
||||
SCVipResourceRes? shortBadge,
|
||||
SCVipResourceRes? avatarFrame,
|
||||
SCVipResourceRes? entryEffect,
|
||||
SCVipResourceRes? chatBubble,
|
||||
SCVipResourceRes? floatPicture,
|
||||
SCVipResourceRes? backgroundCard,
|
||||
SCVipResourceRes? effectImage,
|
||||
bool? canPurchase,
|
||||
num? payableGold,
|
||||
}) {
|
||||
@ -248,10 +282,14 @@ class SCVipLevelConfigRes {
|
||||
_durationDays = durationDays;
|
||||
_priceGold = priceGold;
|
||||
_badge = badge;
|
||||
_longBadge = longBadge;
|
||||
_shortBadge = shortBadge;
|
||||
_avatarFrame = avatarFrame;
|
||||
_entryEffect = entryEffect;
|
||||
_chatBubble = chatBubble;
|
||||
_floatPicture = floatPicture;
|
||||
_backgroundCard = backgroundCard;
|
||||
_effectImage = effectImage;
|
||||
_canPurchase = canPurchase;
|
||||
_payableGold = payableGold;
|
||||
}
|
||||
@ -266,10 +304,14 @@ class SCVipLevelConfigRes {
|
||||
_durationDays = _numValue(map['durationDays']);
|
||||
_priceGold = _numValue(map['priceGold']);
|
||||
_badge = _resourceValue(map['badge']);
|
||||
_longBadge = _resourceValue(map['longBadge']) ?? _badge;
|
||||
_shortBadge = _resourceValue(map['shortBadge']);
|
||||
_avatarFrame = _resourceValue(map['avatarFrame']);
|
||||
_entryEffect = _resourceValue(map['entryEffect']);
|
||||
_chatBubble = _resourceValue(map['chatBubble']);
|
||||
_floatPicture = _resourceValue(map['floatPicture']);
|
||||
_backgroundCard = _resourceValue(map['backgroundCard']);
|
||||
_effectImage = _resourceValue(map['effectImage']);
|
||||
_canPurchase = _boolValue(map['canPurchase']);
|
||||
_payableGold = _numValue(map['payableGold']);
|
||||
}
|
||||
@ -281,10 +323,14 @@ class SCVipLevelConfigRes {
|
||||
num? _durationDays;
|
||||
num? _priceGold;
|
||||
SCVipResourceRes? _badge;
|
||||
SCVipResourceRes? _longBadge;
|
||||
SCVipResourceRes? _shortBadge;
|
||||
SCVipResourceRes? _avatarFrame;
|
||||
SCVipResourceRes? _entryEffect;
|
||||
SCVipResourceRes? _chatBubble;
|
||||
SCVipResourceRes? _floatPicture;
|
||||
SCVipResourceRes? _backgroundCard;
|
||||
SCVipResourceRes? _effectImage;
|
||||
bool? _canPurchase;
|
||||
num? _payableGold;
|
||||
|
||||
@ -300,7 +346,11 @@ class SCVipLevelConfigRes {
|
||||
|
||||
num? get priceGold => _priceGold;
|
||||
|
||||
SCVipResourceRes? get badge => _badge;
|
||||
SCVipResourceRes? get badge => longBadge;
|
||||
|
||||
SCVipResourceRes? get longBadge => _longBadge ?? _badge;
|
||||
|
||||
SCVipResourceRes? get shortBadge => _shortBadge;
|
||||
|
||||
SCVipResourceRes? get avatarFrame => _avatarFrame;
|
||||
|
||||
@ -310,6 +360,10 @@ class SCVipLevelConfigRes {
|
||||
|
||||
SCVipResourceRes? get floatPicture => _floatPicture;
|
||||
|
||||
SCVipResourceRes? get backgroundCard => _backgroundCard;
|
||||
|
||||
SCVipResourceRes? get effectImage => _effectImage;
|
||||
|
||||
bool? get canPurchase => _canPurchase;
|
||||
|
||||
num? get payableGold => _payableGold;
|
||||
@ -332,11 +386,17 @@ class SCVipLevelConfigRes {
|
||||
map['enabled'] = _enabled;
|
||||
map['durationDays'] = _durationDays;
|
||||
map['priceGold'] = _priceGold;
|
||||
if (_badge != null) map['badge'] = _badge?.toJson();
|
||||
if (badge != null) map['badge'] = badge?.toJson();
|
||||
if (longBadge != null) map['longBadge'] = longBadge?.toJson();
|
||||
if (_shortBadge != null) map['shortBadge'] = _shortBadge?.toJson();
|
||||
if (_avatarFrame != null) map['avatarFrame'] = _avatarFrame?.toJson();
|
||||
if (_entryEffect != null) map['entryEffect'] = _entryEffect?.toJson();
|
||||
if (_chatBubble != null) map['chatBubble'] = _chatBubble?.toJson();
|
||||
if (_floatPicture != null) map['floatPicture'] = _floatPicture?.toJson();
|
||||
if (_backgroundCard != null) {
|
||||
map['backgroundCard'] = _backgroundCard?.toJson();
|
||||
}
|
||||
if (_effectImage != null) map['effectImage'] = _effectImage?.toJson();
|
||||
map['canPurchase'] = _canPurchase;
|
||||
map['payableGold'] = _payableGold;
|
||||
return map;
|
||||
|
||||
@ -1,13 +1,16 @@
|
||||
enum SCPropsType {
|
||||
AVATAR_FRAME,
|
||||
FLOAT_PICTURE,
|
||||
DATA_CARD,
|
||||
CHAT_BUBBLE,
|
||||
RIDE,
|
||||
LAYOUT,
|
||||
THEME,
|
||||
BADGE,
|
||||
NOBLE_VIP,
|
||||
FRAGMENTS,
|
||||
RED_PACKET,
|
||||
}
|
||||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
enum SCPropsType {
|
||||
AVATAR_FRAME,
|
||||
FLOAT_PICTURE,
|
||||
DATA_CARD,
|
||||
CHAT_BUBBLE,
|
||||
RIDE,
|
||||
LAYOUT,
|
||||
THEME,
|
||||
BADGE,
|
||||
NOBLE_VIP,
|
||||
VIP_EFFECT_IMAGE,
|
||||
FRAGMENTS,
|
||||
RED_PACKET,
|
||||
}
|
||||
|
||||
@ -362,6 +362,7 @@ class _LoopingDataCardVapVideoState extends State<_LoopingDataCardVapVideo> {
|
||||
_controller = controller;
|
||||
controller.setAnimListener(
|
||||
onFailed: (_, __, ___) => _markFailed(),
|
||||
onVideoComplete: _handleVideoComplete,
|
||||
onVideoStart: () {
|
||||
if (mounted && _failed) {
|
||||
setState(() => _failed = false);
|
||||
@ -371,6 +372,19 @@ class _LoopingDataCardVapVideoState extends State<_LoopingDataCardVapVideo> {
|
||||
_play();
|
||||
}
|
||||
|
||||
void _handleVideoComplete() {
|
||||
if (!mounted || !widget.loop || _failed) {
|
||||
return;
|
||||
}
|
||||
unawaited(
|
||||
Future<void>.delayed(Duration.zero, () {
|
||||
if (mounted && widget.loop && !_failed) {
|
||||
return _play();
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _play() async {
|
||||
final controller = _controller;
|
||||
final url = widget.url.trim();
|
||||
|
||||
@ -270,7 +270,11 @@ class _RoomUserInfoCardState extends State<RoomUserInfoCard> {
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
SCDataCardResourceView(resource: dataCard, fit: BoxFit.cover),
|
||||
SCDataCardResourceView(
|
||||
resource: dataCard,
|
||||
fit: BoxFit.fill,
|
||||
fallback: DecoratedBox(decoration: _sheetDecoration()),
|
||||
),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user