creek

The AI Image Editor of 2030

lib/ui/widgets/file_card.dart (5887B)


  1import 'dart:io';
  2import 'package:flutter/material.dart';
  3import 'package:creekui/data/models/file_model.dart';
  4import 'package:creekui/ui/styles/variables.dart';
  5
  6class FileCard extends StatelessWidget {
  7  final FileModel file;
  8  final String breadcrumb;
  9  final String dimensions;
 10  final String previewPath;
 11  final String timeAgo;
 12  final VoidCallback onTap;
 13
 14  // Optional actions for the context menu
 15  final Function(String)? onMenuAction;
 16
 17  const FileCard({
 18    super.key,
 19    required this.file,
 20    required this.breadcrumb,
 21    required this.dimensions,
 22    required this.previewPath,
 23    required this.timeAgo,
 24    required this.onTap,
 25    this.onMenuAction,
 26  });
 27
 28  @override
 29  Widget build(BuildContext context) {
 30    return GestureDetector(
 31      onTap: onTap,
 32      child: Container(
 33        height: 110,
 34        decoration: BoxDecoration(
 35          color: Variables.background,
 36          borderRadius: BorderRadius.circular(Variables.radiusMedium),
 37          border: Border.all(color: Variables.borderSubtle),
 38        ),
 39        padding: const EdgeInsets.all(12),
 40        child: Row(
 41          children: [
 42            // Preview Image
 43            Container(
 44              width: 76,
 45              height: 76,
 46              decoration: BoxDecoration(
 47                color: Variables.surfaceSubtle,
 48                borderRadius: BorderRadius.circular(Variables.radiusSmall),
 49              ),
 50              clipBehavior: Clip.antiAlias,
 51              child:
 52                  previewPath.isNotEmpty
 53                      ? Image.file(
 54                        File(previewPath),
 55                        fit: BoxFit.cover,
 56                        errorBuilder:
 57                            (context, error, stackTrace) => const Center(
 58                              child: Icon(
 59                                Icons.broken_image,
 60                                color: Variables.textDisabled,
 61                              ),
 62                            ),
 63                      )
 64                      : const Center(
 65                        child: Icon(Icons.image, color: Variables.textDisabled),
 66                      ),
 67            ),
 68            const SizedBox(width: 16),
 69            // Info
 70            Expanded(
 71              child: Column(
 72                crossAxisAlignment: CrossAxisAlignment.start,
 73                mainAxisAlignment: MainAxisAlignment.center,
 74                children: [
 75                  if (breadcrumb.isNotEmpty)
 76                    Padding(
 77                      padding: const EdgeInsets.only(bottom: 4),
 78                      child: Text(
 79                        breadcrumb,
 80                        style: Variables.captionStyle,
 81                        maxLines: 1,
 82                        overflow: TextOverflow.ellipsis,
 83                      ),
 84                    ),
 85                  Text(
 86                    file.name,
 87                    style: Variables.bodyStyle.copyWith(
 88                      fontWeight: FontWeight.w600,
 89                    ),
 90                    maxLines: 1,
 91                    overflow: TextOverflow.ellipsis,
 92                  ),
 93                  const SizedBox(height: 4),
 94                  Text(dimensions, style: Variables.captionStyle),
 95                  const SizedBox(height: 2),
 96                  Text(
 97                    timeAgo,
 98                    style: Variables.captionStyle.copyWith(
 99                      color: Variables.textSecondary,
100                    ),
101                  ),
102                ],
103              ),
104            ),
105            // Menu Action
106            if (onMenuAction != null)
107              PopupMenuButton<String>(
108                icon: const Icon(
109                  Icons.more_vert,
110                  color: Variables.textSecondary,
111                ),
112                onSelected: onMenuAction,
113                itemBuilder:
114                    (BuildContext context) => <PopupMenuEntry<String>>[
115                      const PopupMenuItem<String>(
116                        value: 'open',
117                        child: Row(
118                          children: [
119                            Icon(Icons.file_open_outlined, size: 18),
120                            SizedBox(width: 12),
121                            Text(
122                              'Open',
123                              style: TextStyle(fontFamily: 'GeneralSans'),
124                            ),
125                          ],
126                        ),
127                      ),
128                      const PopupMenuItem<String>(
129                        value: 'rename',
130                        child: Row(
131                          children: [
132                            Icon(Icons.edit_outlined, size: 18),
133                            SizedBox(width: 12),
134                            Text(
135                              'Rename',
136                              style: TextStyle(fontFamily: 'GeneralSans'),
137                            ),
138                          ],
139                        ),
140                      ),
141                      const PopupMenuItem<String>(
142                        value: 'delete',
143                        child: Row(
144                          children: [
145                            Icon(
146                              Icons.delete_outline,
147                              size: 18,
148                              color: Colors.red,
149                            ),
150                            SizedBox(width: 12),
151                            Text(
152                              'Delete',
153                              style: TextStyle(
154                                fontFamily: 'GeneralSans',
155                                color: Colors.red,
156                              ),
157                            ),
158                          ],
159                        ),
160                      ),
161                    ],
162              ),
163          ],
164        ),
165      ),
166    );
167  }
168}