Skip to content

Commit

Permalink
Merge branch 'main' into feat/bump-flutter-ci-to-3.2.04
Browse files Browse the repository at this point in the history
  • Loading branch information
minikin authored Sep 18, 2024
2 parents 4dd795b + e00567e commit f99dc6b
Show file tree
Hide file tree
Showing 9 changed files with 263 additions and 47 deletions.
16 changes: 16 additions & 0 deletions catalyst_voices/lib/common/ext/space_ext.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
import 'package:catalyst_voices/routes/routes.dart';
import 'package:catalyst_voices_assets/catalyst_voices_assets.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:flutter/material.dart';

extension SpaceExt on Space {
void go(BuildContext context) {
switch (this) {
case Space.treasury:
const TreasuryRoute().go(context);
case Space.discovery:
const DiscoveryRoute().go(context);
case Space.workspace:
const WorkspaceRoute().go(context);
case Space.voting:
const VotingRoute().go(context);
case Space.fundedProjects:
const FundedProjectsRoute().go(context);
}
}

String localizedName(VoicesLocalizations localizations) {
return switch (this) {
Space.treasury => localizations.spaceTreasuryName,
Expand Down
37 changes: 16 additions & 21 deletions catalyst_voices/lib/pages/spaces/drawer/spaces_drawer.dart
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import 'dart:async';

import 'package:catalyst_voices/common/ext/ext.dart';
import 'package:catalyst_voices/pages/spaces/drawer/discovery_menu.dart';
import 'package:catalyst_voices/pages/spaces/drawer/guest_menu.dart';
import 'package:catalyst_voices/pages/spaces/drawer/individual_private_campaigns.dart';
import 'package:catalyst_voices/pages/spaces/drawer/my_private_proposals.dart';
import 'package:catalyst_voices/pages/spaces/drawer/voting_rounds.dart';
import 'package:catalyst_voices/routes/routes.dart';
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:flutter/material.dart';

class SpacesDrawer extends StatelessWidget {
final Space space;
final Map<Space, ShortcutActivator> spacesShortcutsActivators;
final bool isUnlocked;

const SpacesDrawer({
super.key,
required this.space,
this.spacesShortcutsActivators = const {},
this.isUnlocked = false,
});

Expand All @@ -25,13 +29,22 @@ class SpacesDrawer extends StatelessWidget {
return VoicesDrawer(
bottom: VoicesDrawerSpaceChooser(
currentSpace: space,
onChanged: (space) {
_goTo(context, space: space);
},
onChanged: (space) => space.go(context),
onOverallTap: () {
Scaffold.of(context).closeDrawer();
unawaited(const OverallSpacesRoute().push<void>(context));
},
builder: (context, value, child) {
final shortcutActivator = spacesShortcutsActivators[value];

return VoicesPlainTooltip(
message: value.localizedName(context.l10n),
trailing: shortcutActivator != null
? ShortcutActivatorView(activator: shortcutActivator)
: null,
child: child!,
);
},
),
children: [
_menuBuilder(),
Expand All @@ -49,22 +62,4 @@ class SpacesDrawer extends StatelessWidget {
Space.fundedProjects => const SizedBox.shrink(),
};
}

void _goTo(
BuildContext context, {
required Space space,
}) {
switch (space) {
case Space.treasury:
const TreasuryRoute().go(context);
case Space.discovery:
const DiscoveryRoute().go(context);
case Space.workspace:
const WorkspaceRoute().go(context);
case Space.voting:
const VotingRoute().go(context);
case Space.fundedProjects:
const FundedProjectsRoute().go(context);
}
}
}
62 changes: 47 additions & 15 deletions catalyst_voices/lib/pages/spaces/spaces_shell_page.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
import 'package:catalyst_voices/common/ext/ext.dart';
import 'package:catalyst_voices/pages/spaces/drawer/spaces_drawer.dart';
import 'package:catalyst_voices/widgets/widgets.dart';
import 'package:catalyst_voices_blocs/catalyst_voices_blocs.dart';
import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class SpacesShellPage extends StatelessWidget {
final Space space;
final Widget child;

static final Map<Space, ShortcutActivator> _spacesShortcutsActivators = {
Space.discovery: LogicalKeySet(
LogicalKeyboardKey.control,
LogicalKeyboardKey.digit1,
),
Space.workspace: LogicalKeySet(
LogicalKeyboardKey.control,
LogicalKeyboardKey.digit2,
),
Space.voting: LogicalKeySet(
LogicalKeyboardKey.control,
LogicalKeyboardKey.digit3,
),
Space.fundedProjects: LogicalKeySet(
LogicalKeyboardKey.control,
LogicalKeyboardKey.digit4,
),
Space.treasury: LogicalKeySet(
LogicalKeyboardKey.control,
LogicalKeyboardKey.keyT,
),
};

const SpacesShellPage({
super.key,
required this.space,
Expand All @@ -21,22 +46,29 @@ class SpacesShellPage extends StatelessWidget {
final isVisitor = sessionBloc.state is VisitorSessionState;
final isUnlocked = sessionBloc.state is ActiveUserSessionState;

return Scaffold(
appBar: VoicesAppBar(
leading: isVisitor ? null : const DrawerToggleButton(),
automaticallyImplyLeading: false,
actions: const [
SessionActionHeader(),
SessionStateHeader(),
],
return CallbackShortcuts(
bindings: <ShortcutActivator, VoidCallback>{
for (final entry in _spacesShortcutsActivators.entries)
entry.value: () => entry.key.go(context),
},
child: Scaffold(
appBar: VoicesAppBar(
leading: isVisitor ? null : const DrawerToggleButton(),
automaticallyImplyLeading: false,
actions: const [
SessionActionHeader(),
SessionStateHeader(),
],
),
drawer: isVisitor
? null
: SpacesDrawer(
space: space,
spacesShortcutsActivators: _spacesShortcutsActivators,
isUnlocked: isUnlocked,
),
body: child,
),
drawer: isVisitor
? null
: SpacesDrawer(
space: space,
isUnlocked: isUnlocked,
),
body: child,
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import 'package:catalyst_voices/widgets/tooltips/voices_plain_tooltip.dart';
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
import 'package:flutter/material.dart';

/// Widget that is meant to be used as singular keyboard key indication.
///
/// Common use case is to show list of such keys that together means
/// shortcut of some sorts.
///
/// See:
/// * [VoicesPlainTooltip] as good starting points for used of this button.
class VoicesKeyboardKeyButton extends StatelessWidget {
/// Usually [Icon], [CatalystSvgIcon] or [Text].
final Widget child;

const VoicesKeyboardKeyButton({
super.key,
required this.child,
});

@override
Widget build(BuildContext context) {
final theme = Theme.of(context);

final iconTheme = IconThemeData(
size: 14,
color: theme.colors.iconsForeground,
);

final textStyle = TextStyle(
fontSize: 14,
fontWeight: FontWeight.w700,
height: 1,
color: theme.colors.textPrimary,
);

return IconTheme(
data: iconTheme,
child: DefaultTextStyle(
style: textStyle,
textAlign: TextAlign.center,
child: ConstrainedBox(
constraints: const BoxConstraints(minWidth: 23.3, minHeight: 23.3),
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4.6),
color: const Color(0xFFD9D9D9),
),
child: Container(
margin: const EdgeInsets.only(
left: 2.3,
top: 1.17,
right: 2.3,
bottom: 3.5,
),
decoration: BoxDecoration(
color: theme.colorScheme.onPrimary,
borderRadius: BorderRadius.circular(2.3),
),
alignment: Alignment.center,
child: child,
),
),
),
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:catalyst_voices/widgets/buttons/voices_keyboard_key_button.dart';
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

final Map<int, SvgGenImage> _keyIconMapping = {
LogicalKeyboardKey.control.keyId: VoicesAssets.icons.chevronUp,
};

/// Wrapper for [VoicesKeyboardKeyButton] and [LogicalKeyboardKey].
///
/// This widget takes care or proper mapping of [data] to corresponding
/// widget that should indicate given key.
///
/// See [_keyIconMapping] for list of icons with iconographic representation. If
/// no icon is found for such [LogicalKeyboardKey] first letter
/// of [LogicalKeyboardKey.keyLabel] will be used as fallback.
class VoicesLogicalKeyboardKeyButton extends StatelessWidget {
final LogicalKeyboardKey data;

const VoicesLogicalKeyboardKeyButton(
this.data, {
super.key,
});

@override
Widget build(BuildContext context) {
return VoicesKeyboardKeyButton(
child: _buildKeyIndicator(context),
);
}

Widget _buildKeyIndicator(BuildContext context) {
final keyIcon = _keyIconMapping[data.keyId];
if (keyIcon != null) {
return keyIcon.buildIcon();
}

final keyLabel = data.keyLabel;
final letter = keyLabel.isNotEmpty ? keyLabel.substring(0, 1) : null;
if (letter != null) {
return Text(letter.toUpperCase());
}

return const SizedBox.shrink();
}
}
31 changes: 31 additions & 0 deletions catalyst_voices/lib/widgets/common/shortcut_activator_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:catalyst_voices/widgets/buttons/voices_logical_keyboard_key_button.dart';
import 'package:catalyst_voices_shared/catalyst_voices_shared.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';

/// Grouping all [LogicalKeyboardKey] that correspond with given [activator]
/// and shows them in a [Row] as [VoicesLogicalKeyboardKeyButton].
///
/// This widget also uses [LogicalKeyboardKey.collapseSynonyms] to remove
/// any synonyms key activator such as left Control and right Control.
class ShortcutActivatorView extends StatelessWidget {
final ShortcutActivator activator;

const ShortcutActivatorView({
super.key,
required this.activator,
});

@override
Widget build(BuildContext context) {
final triggers = {...?activator.triggers};

return Row(
mainAxisSize: MainAxisSize.min,
children: LogicalKeyboardKey.collapseSynonyms(triggers)
.map<Widget>(VoicesLogicalKeyboardKeyButton.new)
.separatedBy(const SizedBox(width: 4))
.toList(),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ class VoicesDrawerSpaceChooser extends StatelessWidget {
final Space currentSpace;
final ValueChanged<Space> onChanged;
final VoidCallback? onOverallTap;
final ValueWidgetBuilder<Space>? builder;

const VoicesDrawerSpaceChooser({
super.key,
required this.currentSpace,
required this.onChanged,
this.onOverallTap,
this.builder,
});

@override
Expand All @@ -36,13 +38,18 @@ class VoicesDrawerSpaceChooser extends StatelessWidget {
required Space item,
required bool isSelected,
}) {
if (isSelected) {
return SpaceAvatar(
item,
key: ValueKey('DrawerChooser${item}AvatarKey'),
);
} else {
return const VoicesDrawerChooserItemPlaceholder();
Widget child = isSelected
? SpaceAvatar(
item,
key: ValueKey('DrawerChooser${item}AvatarKey'),
)
: const VoicesDrawerChooserItemPlaceholder();

final builder = this.builder;
if (builder != null) {
child = builder(context, item, child);
}

return child;
}
}
Loading

0 comments on commit f99dc6b

Please sign in to comment.