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>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../providers/session_controller.dart';
|
||||
import '../../theme/design_tokens.dart';
|
||||
import '../noo/core/noo_button.dart';
|
||||
import '../noo/noo_layout.dart';
|
||||
import '../noo/overlays/noo_dialog.dart';
|
||||
import '../noo/overlays/noo_overlay_header.dart';
|
||||
import '../noo/overlays/noo_sheet.dart';
|
||||
|
||||
/// Shared by the account card's own quick "Remove account" action and each
|
||||
/// row in the saved-accounts list - same confirm/remove/pop-to-root gate
|
||||
/// either way (mirrors the pre-rework `_confirmRemoveActive`/
|
||||
/// `_AccountsCard._confirmRemove`), just restyled as [showNooDialog]
|
||||
/// (desktop) / [showNooSheet] (mobile) instead of an [AlertDialog].
|
||||
Future<void> confirmRemoveAccount(
|
||||
BuildContext context,
|
||||
SessionController session, {
|
||||
required String accountId,
|
||||
required String username,
|
||||
required String host,
|
||||
required bool isActive,
|
||||
}) async {
|
||||
final hasOtherAccounts = session.accounts.length > 1;
|
||||
final message = isActive && hasOtherAccounts
|
||||
? 'Remove $username ($host)? Another saved account will become active.'
|
||||
: 'Remove $username ($host)? You can add it again later.';
|
||||
|
||||
var confirmed = false;
|
||||
void cancel() => Navigator.pop(context);
|
||||
void confirm() {
|
||||
confirmed = true;
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
Widget buttons(NooColors colors) => Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: NooButton(
|
||||
variant: NooButtonVariant.secondary,
|
||||
size: NooButtonSize.card,
|
||||
fullWidth: true,
|
||||
onTap: cancel,
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: NooSpace.sm),
|
||||
Expanded(
|
||||
child: NooButton(
|
||||
variant: NooButtonVariant.danger,
|
||||
size: NooButtonSize.card,
|
||||
fullWidth: true,
|
||||
onTap: confirm,
|
||||
child: const Text('Remove'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final colors = context.nooColors;
|
||||
if (NooLayout.isDesktop(context)) {
|
||||
await showNooDialog(
|
||||
context,
|
||||
title: 'Remove account',
|
||||
children: [
|
||||
Text(message, style: NooText.body.copyWith(color: colors.fg2)),
|
||||
buttons(colors),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
await showNooSheet(
|
||||
context,
|
||||
children: [
|
||||
NooOverlayHeader(title: 'Remove account', onClose: cancel),
|
||||
Text(message, style: NooText.body.copyWith(color: colors.fg2)),
|
||||
buttons(colors),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
if (!confirmed) return;
|
||||
if (!context.mounted) return;
|
||||
final navigator = Navigator.of(context);
|
||||
await session.removeAccount(accountId);
|
||||
// Only when this was the last saved account does isLoggedIn drop to false
|
||||
// and main.dart swap the root route to LoginView underneath - pop back to
|
||||
// it then, rather than leaving Settings stranded on top. Removing a
|
||||
// non-active account, or falling back to another one, both keep the user
|
||||
// logged in, so Settings should just stay put.
|
||||
if (!session.isLoggedIn) {
|
||||
navigator.popUntil((route) => route.isFirst);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user