Files
noo/lib/widgets/details/details_activity_tab.dart
ayushyaandClaude Opus 5.5 56784ef212 Rebuild UI on the Noo design system
Replaces the Material 3 screens with the Noo design system: warm
neutrals, one violet accent, pill controls, Schibsted Grotesk/
Instrument Sans, Lucide icons, no gradients/shadows.

- New lib/widgets/noo/ component kit (core, lists, files, media, nav,
  overlays) plus lib/theme/design_tokens.dart for the color/type/space/
  radius/motion tokens.
- Rebuilt the app shell (top/bottom bars, drawer, desktop sidebar and
  toolbar), every tab (Files/Offline, Photos, Favorites, Recent,
  Activity, Trash, Shares), Settings, the lock and login screens, the
  media viewer, search, the details/share sheets, and the share-upload
  and move/copy destination pickers.
- Added a design canvas (linked from DESIGN_SYSTEM.md) covering the
  screens the spec didn't already describe, with matching Android and
  iOS chrome; wrote up the approved recipes into DESIGN_SYSTEM.md §4.
- Removed now-dead legacy widgets (media_grid_tile, swipeable_item,
  sync_status_badge, selectable_thumbnail) and updated
  architecture.md/styling.md/standards.md to describe the new
  structure and component/testing conventions.
- Added widget tests for the noo/ component kit.

This is a UI-only rework: no provider/model/service behavior changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 01:51:58 -04:00

95 lines
2.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import 'package:provider/provider.dart';
import '../../models/nextcloud_item.dart';
import '../../providers/item_operations.dart';
import '../../providers/session_controller.dart';
import '../../theme/design_tokens.dart';
import '../noo/lists/noo_grouped_list.dart';
import '../noo/media/noo_activity_item.dart';
import '../noo/media/noo_photo_tile.dart';
/// Per-file activity feed - the same actor/verb/tail mapping and
/// avatar-palette convention as the account-wide Activity tab
/// (`activity_view.dart`), scoped to a single item.
class DetailsActivityTab extends StatefulWidget {
final NextcloudItem item;
const DetailsActivityTab({super.key, required this.item});
@override
State<DetailsActivityTab> createState() => _DetailsActivityTabState();
}
class _DetailsActivityTabState extends State<DetailsActivityTab> {
bool _requested = false;
bool _isLoading = true;
List<NextcloudActivity> _activities = [];
Future<void> _load() async {
final ops = context.read<ItemOperations>();
final result = await ops.fetchFileActivity(widget.item);
if (!mounted) return;
setState(() {
_activities = result;
_isLoading = false;
});
}
@override
Widget build(BuildContext context) {
if (!_requested) {
_requested = true;
WidgetsBinding.instance.addPostFrameCallback((_) => _load());
}
final colors = context.nooColors;
final session = context.watch<SessionController>();
if (_isLoading) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 32),
child: Center(child: CircularProgressIndicator()),
);
}
if (_activities.isEmpty) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 32),
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(LucideIcons.activity, size: 40, color: colors.fg3),
const SizedBox(height: NooSpace.sm),
Text(
'No recent activity',
style: NooText.cardTitle.copyWith(fontSize: 16, color: colors.fg2),
),
],
),
),
);
}
return NooGroupedList(
children: [
for (final act in _activities)
ColoredBox(
color: colors.surface,
child: NooActivityItem(
actor: act.author,
verb: act.title,
tail: act.subject.isNotEmpty && act.subject != act.title
? act.subject
: null,
time: DateFormat.yMMMd().add_jm().format(act.timestamp),
avatarColor: NooPhotoTile.paletteColor(act.author.hashCode),
currentUser:
act.author.toLowerCase() == session.username.toLowerCase(),
),
),
],
);
}
}