Skip to content

Commit

Permalink
feat(cat-voices): updated account page layout (#1728)
Browse files Browse the repository at this point in the history
* chore: cleanup

* chore: scaffolding

* chore: spacings

* feat: flexible catalyst id text

* chore: adjust AccountHeaderTile sizes

* feat: catalyst id background color

* refactor: extract EditableTile from DocumentBuilderSectionTile

* feat: property tile

* feat: account bloc

* chore: wip

* feat: displayName and email

* feat: displayName and email

* feat: navigation back

* feat: roles

* feat: roles small icons

* feat: wallet connected

* feat: cubit linking

* feat: account status

* feat: status banner

* chore: status notification adjustments

* chore: move remove keychain dialogs

* feat: app bar

* account header tile

* fix: default text field decoration is filled

* feat: little adjustments

* chore: missing banner icon

* feat: edit role dialog

* chore: remove test code

* fix: linter

* refactor: extract isOffstage in _AccountStatusBannerState

* chore: comment

* chore: strings dots

* chore: rename stakeAddress
  • Loading branch information
damian-molinski authored Feb 4, 2025
1 parent c0cdf88 commit 530d89a
Show file tree
Hide file tree
Showing 51 changed files with 1,796 additions and 604 deletions.
3 changes: 3 additions & 0 deletions catalyst_voices/apps/voices/lib/app/view/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class _AppState extends State<App> {
BlocProvider<DiscoveryCubit>(
create: (context) => Dependencies.instance.get<DiscoveryCubit>(),
),
BlocProvider<AccountCubit>(
create: (context) => Dependencies.instance.get<AccountCubit>(),
),
];
}
}
30 changes: 22 additions & 8 deletions catalyst_voices/apps/voices/lib/common/ext/account_role_ext.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:flutter/material.dart';

extension AccountRoleExt on AccountRole {
String getName(BuildContext context) {
switch (this) {
case AccountRole.voter:
return context.l10n.voter;
case AccountRole.proposer:
return context.l10n.proposer;
case AccountRole.drep:
return context.l10n.drep;
String getName(
BuildContext context, {
bool addDefaultState = false,
}) {
var name = switch (this) {
AccountRole.voter => context.l10n.voter,
AccountRole.proposer => context.l10n.proposer,
AccountRole.drep => context.l10n.drep,
};

if (addDefaultState && isDefault) {
name = '$name (${context.l10n.defaultRole})';
}

return name;
}

String getVerboseName(BuildContext context) {
Expand Down Expand Up @@ -70,4 +76,12 @@ extension AccountRoleExt on AccountRole {
AccountRole.proposer => VoicesAssets.images.roleProposer,
};
}

SvgGenImage get smallIcon {
return switch (this) {
AccountRole.voter => VoicesAssets.icons.vote,
AccountRole.drep => VoicesAssets.icons.documentText,
AccountRole.proposer => VoicesAssets.icons.badgeCheck,
};
}
}
2 changes: 2 additions & 0 deletions catalyst_voices/apps/voices/lib/common/ext/string_ext.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
extension StringExt on String {
String? get firstLetter => isEmpty ? null : substring(0, 1);

String capitalize() {
if (isNotEmpty) {
return '${this[0].toUpperCase()}${substring(1).toLowerCase()}';
Expand Down
3 changes: 3 additions & 0 deletions catalyst_voices/apps/voices/lib/dependency/dependencies.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ final class Dependencies extends DependencyProvider {
return DiscoveryCubit(
get<CampaignService>(),
);
})
..registerFactory<AccountCubit>(() {
return AccountCubit(get<UserService>());
});
}

Expand Down
244 changes: 61 additions & 183 deletions catalyst_voices/apps/voices/lib/pages/account/account_page.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import 'dart:async';

import 'package:catalyst_voices/common/ext/account_role_ext.dart';
import 'package:catalyst_voices/pages/account/account_page_header.dart';
import 'package:catalyst_voices/pages/account/delete_keychain_dialog.dart';
import 'package:catalyst_voices/pages/account/keychain_deleted_dialog.dart';
import 'package:catalyst_voices/routes/routes.dart';
import 'package:catalyst_voices/widgets/buttons/voices_icon_button.dart';
import 'package:catalyst_voices/widgets/buttons/voices_text_button.dart';
import 'package:catalyst_voices/widgets/list/bullet_list.dart';
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
import 'package:catalyst_voices/pages/account/widgets/account_action_tile.dart';
import 'package:catalyst_voices/pages/account/widgets/account_display_name_tile.dart';
import 'package:catalyst_voices/pages/account/widgets/account_email_tile.dart';
import 'package:catalyst_voices/pages/account/widgets/account_header_tile.dart';
import 'package:catalyst_voices/pages/account/widgets/account_keychain_tile.dart';
import 'package:catalyst_voices/pages/account/widgets/account_page_title.dart';
import 'package:catalyst_voices/pages/account/widgets/account_roles_tile.dart';
import 'package:catalyst_voices/pages/account/widgets/account_status_banner.dart';
import 'package:catalyst_voices/pages/spaces/appbar/account_popup/session_account_avatar.dart';
import 'package:catalyst_voices/pages/spaces/appbar/session_action_header.dart';
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

Expand All @@ -25,193 +25,71 @@ final class AccountPage extends StatefulWidget {

class _AccountPageState extends State<AccountPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
padding: const EdgeInsets.all(32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const AccountPageHeader(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 32),
const _Tab(),
const SizedBox(height: 48),
_KeychainCard(
connectedWallet: 'Lace',
roles: const [
AccountRole.voter,
AccountRole.proposer,
AccountRole.drep,
],
defaultRole: AccountRole.voter,
onRemoveKeychain: () => unawaited(_removeKeychain()),
),
],
),
),
],
),
),
);
}

Future<void> _removeKeychain() async {
final confirmed = await DeleteKeychainDialog.show(context);
if (!confirmed) {
return;
}

if (mounted) {
await context.read<SessionCubit>().removeKeychain();
}
void initState() {
super.initState();

if (mounted) {
await KeychainDeletedDialog.show(context);
}

if (mounted) {
const DiscoveryRoute().go(context);
}
unawaited(context.read<AccountCubit>().loadAccountDetails());
}
}

class _Tab extends StatelessWidget {
const _Tab();

@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 1,
child: TabBar(
padding: const EdgeInsets.symmetric(horizontal: 20),
isScrollable: true,
tabs: [
Tab(text: context.l10n.profileAndKeychain),
return Scaffold(
appBar: const VoicesAppBar(
automaticallyImplyLeading: false,
actions: [
VoicesStartProposalButton(),
SessionActionHeader(),
SessionAccountAvatar(),
],
),
);
}
}

class _KeychainCard extends StatelessWidget {
final String? connectedWallet;
final List<AccountRole> roles;
final AccountRole? defaultRole;
final VoidCallback? onRemoveKeychain;

const _KeychainCard({
this.connectedWallet,
this.roles = const <AccountRole>[],
this.defaultRole,
this.onRemoveKeychain,
});

@override
Widget build(BuildContext context) {
return Container(
constraints: const BoxConstraints(maxWidth: 600),
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(
Radius.circular(16),
),
border: Border.all(
color: Theme.of(context).colors.outlineBorderVariant,
width: 1,
),
color: Theme.of(context).colors.elevationsOnSurfaceNeutralLv1White,
),
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
Expanded(
child: Text(
context.l10n.catalystKeychain,
style: Theme.of(context).textTheme.titleLarge,
),
),
VoicesTextButton.custom(
leading: VoicesAssets.icons.x.buildIcon(),
color: Theme.of(context).colors.iconsError,
onTap: onRemoveKeychain,
child: Text(
context.l10n.removeKeychain,
),
),
],
),
if (connectedWallet != null)
Padding(
padding: const EdgeInsets.symmetric(vertical: 24),
child: Text(
context.l10n.walletConnected,
style: Theme.of(context).textTheme.titleMedium,
),
),
if (connectedWallet != null)
Row(
const AccountStatusBanner(),
Expanded(
child: ListView(
padding: const EdgeInsets.all(24),
children: [
VoicesIconButton.filled(
style: ButtonStyle(
padding: WidgetStateProperty.all(EdgeInsets.zero),
foregroundColor: WidgetStateProperty.all(
Theme.of(context).colors.successContainer,
const AccountPageTitle(),
const SizedBox(height: 42),
const Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: AccountHeaderTile()),
SizedBox(width: 28),
Expanded(child: AccountActionTile()),
],
),
const SizedBox(height: 40),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children: const <Widget>[
AccountDisplayNameTile(),
AccountEmailTile(),
].separatedBy(const SizedBox(height: 20)).toList(),
),
),
backgroundColor: WidgetStateProperty.all(
Theme.of(context).colors.success,
const SizedBox(width: 28),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children: const <Widget>[
AccountRolesTile(),
AccountKeychainTile(),
].separatedBy(const SizedBox(height: 20)).toList(),
),
),
),
child: VoicesAssets.icons.check.buildIcon(),
),
const SizedBox(width: 12),
Text(
connectedWallet!,
style: Theme.of(context).textTheme.bodyLarge,
],
),
],
),
if (roles.isNotEmpty)
Padding(
padding: const EdgeInsets.only(
top: 40,
bottom: 24,
),
child: Text(
context.l10n.currentRoleRegistrations,
style: Theme.of(context).textTheme.titleMedium,
),
),
if (roles.isNotEmpty)
Padding(
padding: const EdgeInsets.only(left: 4),
child: BulletList(
items: roles
.map((e) => _formatRoleBullet(e, defaultRole, context))
.toList(),
style: Theme.of(context).textTheme.bodyLarge,
),
),
),
],
),
);
}

String _formatRoleBullet(
AccountRole role,
AccountRole? defaultRole,
BuildContext context,
) {
if (role == defaultRole) {
return '${role.getName(context)} (${context.l10n.defaultRole})';
} else {
return role.getName(context);
}
}
}
Loading

0 comments on commit 530d89a

Please sign in to comment.