145 lines
4.5 KiB
Dart
145 lines
4.5 KiB
Dart
|
|
import 'package:flutter/material.dart';
|
||
|
|
import '../models/tab_data.dart';
|
||
|
|
|
||
|
|
class ItemListTile extends StatelessWidget {
|
||
|
|
final TabData item;
|
||
|
|
final String icon;
|
||
|
|
final VoidCallback onTap;
|
||
|
|
final VoidCallback onDelete;
|
||
|
|
final VoidCallback onTogglePin;
|
||
|
|
final bool extensionMode;
|
||
|
|
|
||
|
|
const ItemListTile({
|
||
|
|
super.key,
|
||
|
|
required this.item,
|
||
|
|
required this.icon,
|
||
|
|
required this.onTap,
|
||
|
|
required this.onDelete,
|
||
|
|
required this.onTogglePin,
|
||
|
|
this.extensionMode = false,
|
||
|
|
});
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
return Card(
|
||
|
|
margin: const EdgeInsets.only(bottom: 8),
|
||
|
|
child: ListTile(
|
||
|
|
leading: CircleAvatar(
|
||
|
|
child: item.favicon.isNotEmpty && item.favicon.startsWith('http')
|
||
|
|
? Image.network(
|
||
|
|
item.favicon,
|
||
|
|
width: 20,
|
||
|
|
height: 20,
|
||
|
|
errorBuilder: (context, error, stackTrace) {
|
||
|
|
return Text(icon, style: const TextStyle(fontSize: 20));
|
||
|
|
},
|
||
|
|
)
|
||
|
|
: Text(icon, style: const TextStyle(fontSize: 20)),
|
||
|
|
),
|
||
|
|
title: Row(
|
||
|
|
children: [
|
||
|
|
if (item.isPinned) ...[
|
||
|
|
Icon(
|
||
|
|
Icons.push_pin,
|
||
|
|
size: 14,
|
||
|
|
color: Theme.of(context).colorScheme.primary,
|
||
|
|
),
|
||
|
|
const SizedBox(width: 4),
|
||
|
|
],
|
||
|
|
Container(
|
||
|
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||
|
|
decoration: BoxDecoration(
|
||
|
|
color: _getTypeColor(context),
|
||
|
|
borderRadius: BorderRadius.circular(4),
|
||
|
|
),
|
||
|
|
child: Text(
|
||
|
|
item.type.toUpperCase(),
|
||
|
|
style: TextStyle(
|
||
|
|
fontSize: 10,
|
||
|
|
color: Theme.of(context).colorScheme.onPrimary,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
const SizedBox(width: 8),
|
||
|
|
Expanded(
|
||
|
|
child: Text(
|
||
|
|
item.title,
|
||
|
|
maxLines: 1,
|
||
|
|
overflow: TextOverflow.ellipsis,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
subtitle: Column(
|
||
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||
|
|
children: [
|
||
|
|
Text(
|
||
|
|
item.url,
|
||
|
|
maxLines: 1,
|
||
|
|
overflow: TextOverflow.ellipsis,
|
||
|
|
),
|
||
|
|
if (item.visitCount != null)
|
||
|
|
Text('${item.visitCount} visits',
|
||
|
|
style: Theme.of(context).textTheme.bodySmall),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
trailing: extensionMode ? null : Row(
|
||
|
|
mainAxisSize: MainAxisSize.min,
|
||
|
|
children: [
|
||
|
|
if (item.type == 'tab')
|
||
|
|
IconButton(
|
||
|
|
icon: Icon(
|
||
|
|
item.isPinned ? Icons.push_pin : Icons.push_pin_outlined,
|
||
|
|
),
|
||
|
|
onPressed: onTogglePin,
|
||
|
|
tooltip: item.isPinned ? 'Unpin' : 'Pin',
|
||
|
|
),
|
||
|
|
if (item.type != 'history')
|
||
|
|
IconButton(
|
||
|
|
icon: const Icon(Icons.delete_outline),
|
||
|
|
onPressed: onDelete,
|
||
|
|
tooltip: 'Delete',
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
onTap: onTap,
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
Color _getTypeColor(BuildContext context) {
|
||
|
|
switch (item.type) {
|
||
|
|
case 'tab':
|
||
|
|
return Colors.blue;
|
||
|
|
case 'bookmark':
|
||
|
|
return Colors.orange;
|
||
|
|
case 'history':
|
||
|
|
return Colors.purple;
|
||
|
|
default:
|
||
|
|
return Theme.of(context).colorScheme.primary;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
// This widget displays a single tab, bookmark, or history item as a list tile in the list view.
|
||
|
|
//
|
||
|
|
// It is the list view alternative to ItemCard and shows the same information in a horizontal layout.
|
||
|
|
//
|
||
|
|
// A circular avatar on the left shows the favicon or emoji icon for the item.
|
||
|
|
//
|
||
|
|
// The title row displays an optional pin icon, type badge, and the item title.
|
||
|
|
//
|
||
|
|
// The subtitle shows the URL and optional visit count below the title.
|
||
|
|
//
|
||
|
|
// Action buttons on the right allow pinning tabs and deleting tabs or bookmarks.
|
||
|
|
//
|
||
|
|
// These buttons are hidden in extension mode and history items do not show delete buttons.
|
||
|
|
//
|
||
|
|
// Tapping anywhere on the tile triggers the onTap callback to open the item.
|
||
|
|
//
|
||
|
|
// The list tile format is more compact and shows more items on screen compared to grid cards.
|
||
|
|
//
|
||
|
|
// Users can toggle between this list view and the grid card view using the view toggle button.
|
||
|
|
//
|
||
|
|
// This provides flexibility in how users prefer to browse their browser items.
|