madari-oss/lib/features/accounts/container/trakt.container.dart
omkar 46571852de
Some checks failed
Build and Deploy / build_windows (push) Has been cancelled
Build and Deploy / build_android (push) Has been cancelled
Build and Deploy / build_ipa (push) Has been cancelled
Build and Deploy / build_linux (push) Has been cancelled
Build and Deploy / build_macos (push) Has been cancelled
fix: small changes
2025-02-06 23:08:55 +05:30

234 lines
6.6 KiB
Dart

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import '../service/zeku_service.dart';
class ServicesGrid extends StatefulWidget {
const ServicesGrid({super.key});
@override
State<ServicesGrid> createState() => _ServicesGridState();
}
class _ServicesGridState extends State<ServicesGrid> {
final _zekuService = ZekuService();
late Future<List<ZekuServiceItem>> _servicesFuture;
@override
void initState() {
super.initState();
_servicesFuture = _zekuService.getServices();
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return FutureBuilder<List<ZekuServiceItem>>(
future: _servicesFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(
color: theme.colorScheme.primary,
),
);
}
if (snapshot.hasError) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.error_outline,
color: theme.colorScheme.error,
size: 48,
),
const SizedBox(height: 16),
Text(
'Failed to load services',
style: theme.textTheme.titleMedium?.copyWith(
color: theme.colorScheme.error,
),
),
const SizedBox(height: 8),
Text(
'${snapshot.error}',
style: theme.textTheme.titleMedium?.copyWith(
color: theme.colorScheme.error,
),
),
const SizedBox(height: 8),
ElevatedButton(
onPressed: () {
setState(() {
_servicesFuture = _zekuService.getServices();
});
},
child: const Text('Retry'),
),
],
),
);
}
final services = snapshot.data ?? [];
if (services.isEmpty) {
return Center(
child: Text(
'No services available',
style: theme.textTheme.titleMedium?.copyWith(
color: theme.colorScheme.onSurface,
),
),
);
}
return ListView.builder(
padding: const EdgeInsets.all(0),
itemCount: services.length,
itemBuilder: (context, index) {
final service = services[index];
return ServiceCard(
service: service,
onRefresh: () {
setState(() {
_servicesFuture = _zekuService.getServices();
});
},
);
},
);
},
);
}
}
class ServiceCard extends StatefulWidget {
final ZekuServiceItem service;
final VoidCallback onRefresh;
const ServiceCard({
super.key,
required this.service,
required this.onRefresh,
});
@override
State<ServiceCard> createState() => _ServiceCardState();
}
class _ServiceCardState extends State<ServiceCard> {
authenticate() async {
await ZekuService.instance.authenticate();
showAdaptiveDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Authenticated?"),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text("Cancel"),
),
TextButton(
child: const Text("Refresh"),
onPressed: () {
widget.onRefresh();
Navigator.pop(context);
},
),
],
);
},
);
}
disconnect(String service) async {
await ZekuService.instance.removeSession(service);
widget.onRefresh();
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: SizedBox(
width: 60,
height: 60,
child: CachedNetworkImage(
imageUrl: widget.service.logo,
fit: BoxFit.cover,
placeholder: (context, url) => Center(
child: CircularProgressIndicator(
strokeWidth: 2,
color: theme.colorScheme.primary,
),
),
errorWidget: (context, url, error) => Container(
color: theme.colorScheme.surfaceContainerHighest,
child: Icon(
Icons.image_not_supported,
color: theme.colorScheme.onSurfaceVariant,
size: 24,
),
),
),
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
widget.service.name,
style: theme.textTheme.titleMedium?.copyWith(
color: theme.colorScheme.onSurface,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 4),
Text(
widget.service.website,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
TextButton(
onPressed: () {
if (widget.service.enabled) {
disconnect(widget.service.name);
} else {
authenticate();
}
},
child: widget.service.enabled
? const Text("Disconnect")
: const Text("Authenticate"),
),
],
),
),
);
}
}