Share sheet now pre-fills: "I'm a BRONZE Explorer on Eventify Plus! 7 EP earned. Let's connect on the platform for more. https://app.eventifyplus.com" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
199 lines
6.8 KiB
Dart
199 lines
6.8 KiB
Dart
import 'dart:io';
|
|
import 'dart:ui' as ui;
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:path_provider/path_provider.dart';
|
|
import 'package:share_plus/share_plus.dart';
|
|
import '../../widgets/tier_avatar_ring.dart';
|
|
|
|
class ShareRankCard extends StatefulWidget {
|
|
final String username;
|
|
final String tier;
|
|
final int rank;
|
|
final int ep;
|
|
final int rewardPoints;
|
|
|
|
const ShareRankCard({
|
|
super.key,
|
|
required this.username,
|
|
required this.tier,
|
|
required this.rank,
|
|
required this.ep,
|
|
this.rewardPoints = 0,
|
|
});
|
|
|
|
@override
|
|
State<ShareRankCard> createState() => _ShareRankCardState();
|
|
}
|
|
|
|
class _ShareRankCardState extends State<ShareRankCard> {
|
|
final GlobalKey _boundaryKey = GlobalKey();
|
|
bool _sharing = false;
|
|
|
|
static const _tierGradients = {
|
|
'Bronze': [Color(0xFF92400E), Color(0xFFD97706)],
|
|
'Silver': [Color(0xFF475569), Color(0xFF94A3B8)],
|
|
'Gold': [Color(0xFF92400E), Color(0xFFFBBF24)],
|
|
'Platinum': [Color(0xFF4C1D95), Color(0xFF8B5CF6)],
|
|
'Diamond': [Color(0xFF1E3A8A), Color(0xFF60A5FA)],
|
|
};
|
|
|
|
List<Color> get _gradient {
|
|
return _tierGradients[widget.tier] ?? [const Color(0xFF0F172A), const Color(0xFF1E293B)];
|
|
}
|
|
|
|
Future<void> _share() async {
|
|
if (_sharing) return;
|
|
setState(() => _sharing = true);
|
|
try {
|
|
final boundary = _boundaryKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
|
|
final image = await boundary.toImage(pixelRatio: 3.0);
|
|
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
|
|
if (byteData == null) return;
|
|
final bytes = byteData.buffer.asUint8List();
|
|
|
|
final tempDir = await getTemporaryDirectory();
|
|
final file = File('${tempDir.path}/eventify_rank_${widget.username}.png');
|
|
await file.writeAsBytes(bytes);
|
|
|
|
await Share.shareXFiles(
|
|
[XFile(file.path)],
|
|
subject: 'My Eventify Rank',
|
|
text: 'I\'m a ${widget.tier.toUpperCase()} Explorer on Eventify Plus! ${widget.ep} EP earned. Let\'s connect on the platform for more.\n\nhttps://app.eventifyplus.com',
|
|
);
|
|
} catch (e) {
|
|
if (mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('Could not share rank card')),
|
|
);
|
|
}
|
|
} finally {
|
|
if (mounted) setState(() => _sharing = false);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
RepaintBoundary(
|
|
key: _boundaryKey,
|
|
child: Container(
|
|
width: 320,
|
|
padding: const EdgeInsets.all(24),
|
|
decoration: BoxDecoration(
|
|
gradient: const LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: [Color(0xFF0F172A), Color(0xFF1E293B)],
|
|
),
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
// Tier gradient header bar
|
|
Container(
|
|
height: 6,
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(colors: _gradient),
|
|
borderRadius: BorderRadius.circular(3),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
// Avatar
|
|
TierAvatarRing(username: widget.username, tier: widget.tier, size: 80),
|
|
const SizedBox(height: 12),
|
|
// Username
|
|
Text(
|
|
widget.username,
|
|
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w800, color: Colors.white),
|
|
),
|
|
const SizedBox(height: 4),
|
|
// Tier badge
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(colors: _gradient),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
child: Text(
|
|
widget.tier.isEmpty ? 'Contributor' : widget.tier,
|
|
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w700, color: Colors.white),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
// Stats row
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: [
|
|
_stat('Rank', '#${widget.rank}'),
|
|
Container(width: 1, height: 40, color: Colors.white12),
|
|
_stat('EP', '${widget.ep}'),
|
|
Container(width: 1, height: 40, color: Colors.white12),
|
|
_stat('RP', '${widget.rewardPoints}'),
|
|
],
|
|
),
|
|
const SizedBox(height: 20),
|
|
// Branding
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: const [
|
|
Icon(Icons.bolt, size: 14, color: Color(0xFF3B82F6)),
|
|
SizedBox(width: 4),
|
|
Text(
|
|
'EVENTIFY',
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w900,
|
|
color: Color(0xFF3B82F6),
|
|
letterSpacing: 2,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 16),
|
|
ElevatedButton.icon(
|
|
onPressed: _sharing ? null : _share,
|
|
icon: _sharing
|
|
? const SizedBox(
|
|
width: 16,
|
|
height: 16,
|
|
child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white),
|
|
)
|
|
: const Icon(Icons.share, size: 18),
|
|
label: Text(_sharing ? 'Sharing...' : 'Share Rank Card'),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: const Color(0xFF1D4ED8),
|
|
foregroundColor: Colors.white,
|
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _stat(String label, String value) {
|
|
return Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Text(
|
|
value,
|
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w800, color: Colors.white),
|
|
),
|
|
const SizedBox(height: 2),
|
|
Text(
|
|
label,
|
|
style: const TextStyle(fontSize: 11, color: Color(0xFF94A3B8)),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|