1
0
forked from baron/baron-sso

App 카드 로고 이미지 표시

This commit is contained in:
2026-04-09 11:27:46 +09:00
parent df09694ed6
commit 06a6875cdb
5 changed files with 290 additions and 31 deletions

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
@@ -1384,6 +1385,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
_ActivityItem(
clientId: rp.id,
appName: name,
logo: rp.logo.trim(),
lastAuthAt: lastAuthLabel,
status: statusCode,
scopes: rp.scopes,
@@ -1522,37 +1524,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
item.appName,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: _ink,
),
),
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: statusColor,
borderRadius: BorderRadius.circular(999),
),
child: Text(
item.status == 'active'
? tr('ui.userfront.dashboard.activity.linked')
: tr('ui.userfront.dashboard.status.revoked'),
style: const TextStyle(
fontSize: 11,
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
),
],
),
_buildActivityCardHeader(item, statusColor),
const SizedBox(height: 10),
Text(
tr('ui.userfront.dashboard.last_auth_label'),
@@ -1658,6 +1630,115 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
return opaqueCard;
}
Widget _buildActivityCardHeader(_ActivityItem item, Color statusColor) {
final statusBadge = Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: statusColor,
borderRadius: BorderRadius.circular(999),
),
child: Text(
item.status == 'active'
? tr('ui.userfront.dashboard.activity.linked')
: tr('ui.userfront.dashboard.status.revoked'),
style: const TextStyle(
fontSize: 11,
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
);
return SizedBox(
height: 40,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (item.logo.isNotEmpty) ...[
_buildActivityLogo(item.logo),
const SizedBox(width: 10),
],
Expanded(
child: Align(
alignment: Alignment.centerLeft,
child: Text(
item.appName,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: _ink,
height: 1.25,
),
),
),
),
const SizedBox(width: 8),
statusBadge,
],
),
);
}
Widget _buildActivityLogo(String logoUrl) {
return SizedBox(
width: 40,
height: 40,
child: _buildActivityLogoImage(logoUrl),
);
}
Widget _buildActivityLogoImage(String logoUrl) {
final isSvg = _isSvgLogoUrl(logoUrl);
return isSvg
? SvgPicture.network(
logoUrl,
fit: BoxFit.contain,
placeholderBuilder: (context) => _buildActivityLogoLoading(),
)
: Image.network(
logoUrl,
fit: BoxFit.contain,
errorBuilder: (context, error, stackTrace) {
return _buildActivityLogoFallback();
},
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) {
return child;
}
return _buildActivityLogoLoading();
},
);
}
bool _isSvgLogoUrl(String logoUrl) {
final normalized = logoUrl.trim().toLowerCase();
if (normalized.isEmpty) {
return false;
}
final uri = Uri.tryParse(normalized);
final path = uri?.path.toLowerCase() ?? normalized;
return path.endsWith('.svg');
}
Widget _buildActivityLogoLoading() {
return Center(
child: SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.grey[400],
),
),
);
}
Widget _buildActivityLogoFallback() {
return Icon(Icons.apps_rounded, size: 20, color: Colors.grey[500]);
}
Widget _buildAccessHistory(AuthTimelineState state, bool isWide) {
final sessionsState = ref.watch(userSessionsProvider);
if (state.isLoading && state.items.isEmpty) {
@@ -2470,6 +2551,7 @@ enum _HistorySessionStatus { current, active, inactive }
class _ActivityItem {
final String clientId;
final String appName;
final String logo;
final String lastAuthAt;
final String status;
final String? url;
@@ -2482,6 +2564,7 @@ class _ActivityItem {
_ActivityItem({
required this.clientId,
required this.appName,
required this.logo,
required this.lastAuthAt,
required this.status,
required this.scopes,