utils
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
Some checks are pending
Backend CI / test (push) Waiting to run
Backend CI / build (push) Blocked by required conditions
Web App CI / test (push) Waiting to run
Web App CI / build (push) Blocked by required conditions
Deploy Mnemo Cards / Deploy Backend (push) Waiting to run
Deploy Mnemo Cards / Deploy Web App (push) Blocked by required conditions
Deploy Mnemo Cards / Final Verification (push) Blocked by required conditions
This commit is contained in:
parent
47005a357a
commit
8b754bbd9f
2 changed files with 116 additions and 6 deletions
|
|
@ -283,15 +283,22 @@ class PackDao extends DatabaseAccessor<AppDatabase> with _$PackDaoMixin {
|
||||||
Future<List<VoiceModel>> getCardVoices(String cardId) async {
|
Future<List<VoiceModel>> getCardVoices(String cardId) async {
|
||||||
print('🔍 DAO getCardVoices: Querying voices for card $cardId');
|
print('🔍 DAO getCardVoices: Querying voices for card $cardId');
|
||||||
|
|
||||||
// First, check if there are any voices in CardVoices table for this card
|
// First, check if there are any voices in VoiceModels table with direct cardId link
|
||||||
|
final directVoicesQuery = select(voiceModels)
|
||||||
|
..where((v) => v.cardId.equals(cardId));
|
||||||
|
final directVoices = await directVoicesQuery.get();
|
||||||
|
print('🔍 DAO getCardVoices: Found ${directVoices.length} voices in VoiceModels with direct cardId link');
|
||||||
|
|
||||||
|
// Check if there are any voices in CardVoices table for this card
|
||||||
final countExpr = cardVoices.cardId.count();
|
final countExpr = cardVoices.cardId.count();
|
||||||
final countQuery = selectOnly(cardVoices)
|
final countQuery = selectOnly(cardVoices)
|
||||||
..addColumns([countExpr])
|
..addColumns([countExpr])
|
||||||
..where(cardVoices.cardId.equals(cardId));
|
..where(cardVoices.cardId.equals(cardId));
|
||||||
final countResult = await countQuery.getSingle();
|
final countResult = await countQuery.getSingle();
|
||||||
final count = countResult.read(countExpr) ?? 0;
|
final count = countResult.read(countExpr) ?? 0;
|
||||||
print('🔍 DAO getCardVoices: Found $count entries in CardVoices table for card $cardId');
|
print('🔍 DAO getCardVoices: Found $count entries in CardVoices junction table for card $cardId');
|
||||||
|
|
||||||
|
// Query through junction table
|
||||||
final query = select(voiceModels).join([
|
final query = select(voiceModels).join([
|
||||||
innerJoin(
|
innerJoin(
|
||||||
cardVoices,
|
cardVoices,
|
||||||
|
|
@ -301,7 +308,13 @@ class PackDao extends DatabaseAccessor<AppDatabase> with _$PackDaoMixin {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
final result = await query.map((row) => row.readTable(voiceModels)).get();
|
final result = await query.map((row) => row.readTable(voiceModels)).get();
|
||||||
print('🔍 DAO getCardVoices: Query returned ${result.length} voices');
|
print('🔍 DAO getCardVoices: Query through junction table returned ${result.length} voices');
|
||||||
|
|
||||||
|
// If junction table query returns nothing but direct link exists, return direct voices
|
||||||
|
if (result.isEmpty && directVoices.isNotEmpty) {
|
||||||
|
print('⚠️ DAO getCardVoices: Junction table is empty but direct link exists! Using direct voices.');
|
||||||
|
return directVoices;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -310,16 +323,44 @@ class PackDao extends DatabaseAccessor<AppDatabase> with _$PackDaoMixin {
|
||||||
Future<void> addVoiceToCard(String cardId, String voiceId) async {
|
Future<void> addVoiceToCard(String cardId, String voiceId) async {
|
||||||
print('🔍 DAO addVoiceToCard: Linking voice $voiceId to card $cardId');
|
print('🔍 DAO addVoiceToCard: Linking voice $voiceId to card $cardId');
|
||||||
try {
|
try {
|
||||||
await into(cardVoices).insert(
|
// Check if voice exists
|
||||||
|
final voice = await getVoiceById(voiceId);
|
||||||
|
if (voice == null) {
|
||||||
|
print('❌ DAO addVoiceToCard: Voice $voiceId does not exist!');
|
||||||
|
throw Exception('Voice $voiceId does not exist');
|
||||||
|
}
|
||||||
|
print('✅ DAO addVoiceToCard: Voice $voiceId exists with cardId=${voice.cardId}');
|
||||||
|
|
||||||
|
// Check if card exists
|
||||||
|
final card = await getCardById(cardId);
|
||||||
|
if (card == null) {
|
||||||
|
print('❌ DAO addVoiceToCard: Card $cardId does not exist!');
|
||||||
|
throw Exception('Card $cardId does not exist');
|
||||||
|
}
|
||||||
|
print('✅ DAO addVoiceToCard: Card $cardId exists');
|
||||||
|
|
||||||
|
// Insert into junction table
|
||||||
|
final result = await into(cardVoices).insert(
|
||||||
CardVoicesCompanion.insert(
|
CardVoicesCompanion.insert(
|
||||||
cardId: cardId,
|
cardId: cardId,
|
||||||
voiceId: voiceId,
|
voiceId: voiceId,
|
||||||
),
|
),
|
||||||
mode: InsertMode.insertOrIgnore,
|
mode: InsertMode.insertOrIgnore,
|
||||||
);
|
);
|
||||||
print('✅ DAO addVoiceToCard: Successfully linked voice $voiceId to card $cardId');
|
print('✅ DAO addVoiceToCard: Insert result: $result');
|
||||||
} catch (e) {
|
|
||||||
|
// Verify the insert
|
||||||
|
final verifyQuery = select(cardVoices)
|
||||||
|
..where((cv) => cv.cardId.equals(cardId) & cv.voiceId.equals(voiceId));
|
||||||
|
final verifyResult = await verifyQuery.getSingleOrNull();
|
||||||
|
if (verifyResult == null) {
|
||||||
|
print('❌ DAO addVoiceToCard: Verification failed! Link was not created.');
|
||||||
|
} else {
|
||||||
|
print('✅ DAO addVoiceToCard: Successfully linked and verified voice $voiceId to card $cardId');
|
||||||
|
}
|
||||||
|
} catch (e, stackTrace) {
|
||||||
print('❌ DAO addVoiceToCard: Error linking voice $voiceId to card $cardId: $e');
|
print('❌ DAO addVoiceToCard: Error linking voice $voiceId to card $cardId: $e');
|
||||||
|
print('Stack trace: $stackTrace');
|
||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
69
mnemo_cards_web_v2/lib/utils/card_image_utils.dart
Normal file
69
mnemo_cards_web_v2/lib/utils/card_image_utils.dart
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
|
||||||
|
import '../domain/config/api_config_v2.dart';
|
||||||
|
|
||||||
|
/// Utility functions for working with card images
|
||||||
|
class CardImageUtils {
|
||||||
|
/// Get the display URL for a card's image
|
||||||
|
///
|
||||||
|
/// Priority:
|
||||||
|
/// 1. imageUrl (presigned URL from backend)
|
||||||
|
/// 2. image if it's a full URL (starts with http/https)
|
||||||
|
/// 3. image if it's a filename - convert to API endpoint URL
|
||||||
|
///
|
||||||
|
/// Returns null if no image is available
|
||||||
|
static String? getCardImageUrl(
|
||||||
|
GameCardDto card,
|
||||||
|
String packId,
|
||||||
|
) {
|
||||||
|
// First priority: use presigned URL if available
|
||||||
|
if (card.imageUrl != null && card.imageUrl!.isNotEmpty) {
|
||||||
|
return card.imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second priority: check if image is a full URL
|
||||||
|
final image = card.image;
|
||||||
|
if (image != null && image.isNotEmpty) {
|
||||||
|
// If it's already a full URL, use it
|
||||||
|
if (image.startsWith('http://') || image.startsWith('https://')) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's a filename, convert to API endpoint URL
|
||||||
|
return ApiConfigV2.getCardImageUrl(packId, card.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the display URL for a card's back image
|
||||||
|
///
|
||||||
|
/// Priority:
|
||||||
|
/// 1. imageBackUrl (presigned URL from backend)
|
||||||
|
/// 2. imageBack if it's a full URL (starts with http/https)
|
||||||
|
/// 3. imageBack if it's a filename - convert to API endpoint URL
|
||||||
|
///
|
||||||
|
/// Returns null if no back image is available
|
||||||
|
static String? getCardImageBackUrl(
|
||||||
|
GameCardDto card,
|
||||||
|
String packId,
|
||||||
|
) {
|
||||||
|
// First priority: use presigned URL if available
|
||||||
|
if (card.imageBackUrl != null && card.imageBackUrl!.isNotEmpty) {
|
||||||
|
return card.imageBackUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second priority: check if imageBack is a full URL
|
||||||
|
final imageBack = card.imageBack;
|
||||||
|
if (imageBack != null && imageBack.isNotEmpty) {
|
||||||
|
// If it's already a full URL, use it
|
||||||
|
if (imageBack.startsWith('http://') || imageBack.startsWith('https://')) {
|
||||||
|
return imageBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's a filename, convert to API endpoint URL
|
||||||
|
return ApiConfigV2.getCardImageBackUrl(packId, card.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue