Created
September 12, 2025 03:51
-
-
Save MarkRatjens/9dcd60141d68ab2f25c409bba1442615 to your computer and use it in GitHub Desktop.
ProjectDropdown
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class ProjectDropdown extends StatelessWidget { | |
| final VoidCallback? onCreateProject; | |
| final VoidCallback? onOpenProject; | |
| final VoidCallback? onCloseProject; | |
| const ProjectDropdown({ | |
| this.onCreateProject, | |
| this.onOpenProject, | |
| this.onCloseProject, | |
| }); | |
| Shipment get shipment => ProjectRepository.shipment; | |
| @override | |
| Widget build(BuildContext context) => AnimatedBuilder( | |
| animation: shipment.notifier, | |
| builder: (context, child) => dropdownContent, | |
| ); | |
| Widget get dropdownContent => Padding( | |
| padding: dropdownPadding, | |
| child: PopupMenuButton<String>( | |
| offset: dropdownOffset, | |
| itemBuilder: (context) => menuItems, | |
| onSelected: executeProjectAction, | |
| child: dropdownButton, | |
| ), | |
| ); | |
| EdgeInsets get dropdownPadding => const EdgeInsets.symmetric(horizontal: 8); | |
| Offset get dropdownOffset => const Offset(0, 40); | |
| List<PopupMenuEntry<String>> get menuItems => [ | |
| if (currentProject != null) ...[ | |
| PopupMenuItem<String>( | |
| value: 'current', | |
| child: currentProjectItem, | |
| ), | |
| const PopupMenuDivider(), | |
| ], | |
| PopupMenuItem<String>( | |
| value: 'create', | |
| child: createMenuItem, | |
| ), | |
| PopupMenuItem<String>( | |
| value: 'open', | |
| child: openMenuItem, | |
| ), | |
| if (currentProject != null) ...[ | |
| const PopupMenuDivider(), | |
| PopupMenuItem<String>( | |
| value: 'close', | |
| child: closeMenuItem, | |
| ), | |
| ], | |
| ]; | |
| Project? get currentProject => shipment.focus as Project?; | |
| Widget get currentProjectItem => Row( | |
| children: [ | |
| const Icon(Icons.folder_open, size: 16), | |
| const SizedBox(width: 8), | |
| Expanded(child: currentProjectDetails), | |
| ], | |
| ); | |
| Widget get currentProjectDetails => Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| Text( | |
| currentProject!.displayTitle, | |
| style: const TextStyle(fontWeight: FontWeight.w500), | |
| ), | |
| if (currentProject!.projectDescription.isNotEmpty) | |
| Text( | |
| currentProject!.projectDescription, | |
| style: TextStyle( | |
| fontSize: 12, | |
| color: WisperaTheme.color('onPrimary').withAlpha(153), | |
| ), | |
| maxLines: 1, | |
| overflow: TextOverflow.ellipsis, | |
| ), | |
| ], | |
| ); | |
| Widget get createMenuItem => menuItem(Icons.add, 'Create New Project'); | |
| Widget get openMenuItem => menuItem(Icons.folder_open, 'Open Project...'); | |
| Widget get closeMenuItem => menuItem(Icons.close, 'Close Project'); | |
| Widget menuItem(IconData icon, String text) => Row( | |
| children: [ | |
| Icon(icon, size: 16), | |
| const SizedBox(width: 8), | |
| Text(text), | |
| ], | |
| ); | |
| Widget get dropdownButton => Container( | |
| padding: buttonPadding, | |
| child: Row( | |
| mainAxisSize: MainAxisSize.min, | |
| children: [ | |
| Text( | |
| currentProject?.displayTitle ?? 'Project', | |
| style: buttonTextStyle, | |
| ), | |
| const SizedBox(width: 4), | |
| Icon( | |
| Icons.arrow_drop_down, | |
| color: WisperaTheme.color('onPrimary').withAlpha(179), | |
| size: 16, | |
| ), | |
| ], | |
| ), | |
| ); | |
| EdgeInsets get buttonPadding => const EdgeInsets.symmetric( | |
| horizontal: 12, | |
| vertical: 8, | |
| ); | |
| TextStyle get buttonTextStyle => TextStyle( | |
| color: WisperaTheme.color('onPrimary').withAlpha(179), | |
| ); | |
| void executeProjectAction(String action) { | |
| switch (action) { | |
| case 'create': | |
| onCreateProject?.call(); | |
| break; | |
| case 'open': | |
| onOpenProject?.call(); | |
| break; | |
| case 'close': | |
| closeCurrentProject(); | |
| break; | |
| case 'current': | |
| // Do nothing - just showing current project info | |
| break; | |
| } | |
| } | |
| void closeCurrentProject() { | |
| shipment.clearFocus(shouldNotify: true); | |
| onCloseProject?.call(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment