From ec4a63b223d6511b57ebef550da33410806de680 Mon Sep 17 00:00:00 2001 From: Adrian Samoticha <86920182+Adrian-Samoticha@users.noreply.github.com> Date: Wed, 17 Jan 2024 17:18:21 +0100 Subject: [PATCH] Fix incorrect sidebar and sidebar item color (#484) --- CHANGELOG.md | 9 +- .../macos/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- lib/src/layout/sidebar/sidebar_item.dart | 2 +- lib/src/layout/sidebar/sidebar_items.dart | 163 ++++++++++++--- lib/src/layout/window.dart | 186 ++++++++++-------- pubspec.lock | 20 +- pubspec.yaml | 2 +- 8 files changed, 251 insertions(+), 135 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd70a111..166aed08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [2.0.3] +### 🛠️ Fixed 🛠️ +* Fixed a bug that caused the sidebar to appear darker than intended. + +### 🔄 Updated 🔄 +* `SidebarItems` has now respects the user’s selected accent color and mimics the look of macOS’ sidebar items more closely. + ## [2.0.2] ### 🛠️ Fixed 🛠️ * Fixed images in generated documentation. @@ -5,7 +12,7 @@ ## [2.0.1] ### 🔄 Updated 🔄 * `PushButton` has received a facelift. It now mimics the look and feel of native macOS buttons more closely. - * **Note:** As a result, its `pressedOpacity` property and the `PushButtonTheme` class have been deprecated. + * **Note:** As a result, its `pressedOpacity` property and the `PushButtonTheme` class have been deprecated. ## [2.0.0] ### 🚨 Breaking Changes 🚨 diff --git a/example/macos/Runner.xcodeproj/project.pbxproj b/example/macos/Runner.xcodeproj/project.pbxproj index 2c562a4e..428da703 100644 --- a/example/macos/Runner.xcodeproj/project.pbxproj +++ b/example/macos/Runner.xcodeproj/project.pbxproj @@ -202,7 +202,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { diff --git a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index fb7259e1..83d88728 100644 --- a/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ + AccentColorListener.instance.currentAccentColor ?? AccentColor.blue; + + /// Returns the sidebar item’s selected color. + Color _getColor(BuildContext context) { + final isMainWindow = WindowMainStateListener.instance.isMainWindow; + + return _ColorProvider.getSelectedColor( + accentColor: _accentColor, + isDarkModeEnabled: MacosTheme.of(context).brightness.isDark, + isWindowMain: isMainWindow, + ); + } + List get _allItems { List result = []; for (var element in items) { @@ -117,39 +134,50 @@ class SidebarItems extends StatelessWidget { final theme = MacosTheme.of(context); return MacosIconTheme.merge( data: const MacosIconThemeData(size: 20), - child: _SidebarItemsConfiguration( - selectedColor: selectedColor ?? theme.primaryColor, - unselectedColor: unselectedColor ?? MacosColors.transparent, - shape: shape ?? _defaultShape, - itemSize: itemSize, - child: ListView( - controller: scrollController, - physics: const ClampingScrollPhysics(), - padding: EdgeInsets.all(10.0 - theme.visualDensity.horizontal), - children: List.generate(items.length, (index) { - final item = items[index]; - if (item.disclosureItems != null) { - return MouseRegion( - cursor: cursor!, - child: _DisclosureSidebarItem( - item: item, - selectedItem: _allItems[currentIndex], - onChanged: (item) { - onChanged(_allItems.indexOf(item)); - }, + child: StreamBuilder( + stream: AccentColorListener.instance.onChanged, + builder: (context, _) { + return StreamBuilder( + stream: WindowMainStateListener.instance.onChanged, + builder: (context, _) { + return _SidebarItemsConfiguration( + selectedColor: selectedColor ?? _getColor(context), + unselectedColor: unselectedColor ?? MacosColors.transparent, + shape: shape ?? _defaultShape, + itemSize: itemSize, + child: ListView( + controller: scrollController, + physics: const ClampingScrollPhysics(), + padding: + EdgeInsets.all(10.0 - theme.visualDensity.horizontal), + children: List.generate(items.length, (index) { + final item = items[index]; + if (item.disclosureItems != null) { + return MouseRegion( + cursor: cursor!, + child: _DisclosureSidebarItem( + item: item, + selectedItem: _allItems[currentIndex], + onChanged: (item) { + onChanged(_allItems.indexOf(item)); + }, + ), + ); + } + return MouseRegion( + cursor: cursor!, + child: _SidebarItem( + item: item, + selected: _allItems[currentIndex] == item, + onClick: () => onChanged(_allItems.indexOf(item)), + ), + ); + }), ), ); - } - return MouseRegion( - cursor: cursor!, - child: _SidebarItem( - item: item, - selected: _allItems[currentIndex] == item, - onClick: () => onChanged(_allItems.indexOf(item)), - ), - ); - }), - ), + }, + ); + }, ), ); } @@ -497,3 +525,74 @@ class __DisclosureSidebarItemState extends State<_DisclosureSidebarItem> ); } } + +class _ColorProvider { + /// Returns the selected color based on the provided parameters. + static Color getSelectedColor({ + required AccentColor accentColor, + required bool isDarkModeEnabled, + required bool isWindowMain, + }) { + if (isDarkModeEnabled) { + if (!isWindowMain) { + return const MacosColor.fromRGBO(76, 78, 65, 1.0); + } + + switch (accentColor) { + case AccentColor.blue: + return const MacosColor.fromRGBO(22, 105, 229, 0.749); + + case AccentColor.purple: + return const MacosColor.fromRGBO(204, 45, 202, 0.749); + + case AccentColor.pink: + return const MacosColor.fromRGBO(229, 74, 145, 0.749); + + case AccentColor.red: + return const MacosColor.fromRGBO(238, 64, 68, 0.749); + + case AccentColor.orange: + return const MacosColor.fromRGBO(244, 114, 0, 0.749); + + case AccentColor.yellow: + return const MacosColor.fromRGBO(233, 176, 0, 0.749); + + case AccentColor.green: + return const MacosColor.fromRGBO(76, 177, 45, 0.749); + + case AccentColor.graphite: + return const MacosColor.fromRGBO(129, 129, 122, 0.824); + } + } + + if (!isWindowMain) { + return const MacosColor.fromRGBO(213, 213, 208, 1.0); + } + + switch (accentColor) { + case AccentColor.blue: + return const MacosColor.fromRGBO(9, 129, 255, 0.749); + + case AccentColor.purple: + return const MacosColor.fromRGBO(162, 28, 165, 0.749); + + case AccentColor.pink: + return const MacosColor.fromRGBO(234, 81, 152, 0.749); + + case AccentColor.red: + return const MacosColor.fromRGBO(220, 32, 40, 0.749); + + case AccentColor.orange: + return const MacosColor.fromRGBO(245, 113, 0, 0.749); + + case AccentColor.yellow: + return const MacosColor.fromRGBO(240, 180, 2, 0.749); + + case AccentColor.green: + return const MacosColor.fromRGBO(66, 174, 33, 0.749); + + case AccentColor.graphite: + return const MacosColor.fromRGBO(174, 174, 167, 0.847); + } + } +} diff --git a/lib/src/layout/window.dart b/lib/src/layout/window.dart index 85c20417..d28511c0 100644 --- a/lib/src/layout/window.dart +++ b/lib/src/layout/window.dart @@ -265,95 +265,113 @@ class _MacosWindowState extends State { minHeight: height, maxHeight: height, ).normalize(), - child: kIsWeb ? ColoredBox( - color: theme.canvasColor, - child: Column( - children: [ - // If an app is running on macOS, apply - // sidebar.topOffset as needed in order to avoid the - // traffic lights. Otherwise, position the sidebar - // by the top of the application's bounds based on - // the presence of sidebar.top. - if (!kIsWeb && sidebar.topOffset > 0) ...[ - SizedBox(height: sidebar.topOffset), - ] else if (sidebar.top != null) ...[ - const SizedBox(height: 12), - ] else - const SizedBox.shrink(), - if (_sidebarScrollController.hasClients && - _sidebarScrollController.offset > 0.0) - Divider(thickness: 1, height: 1, color: dividerColor), - if (sidebar.top != null && constraints.maxHeight > 81) - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8.0), - child: sidebar.top!, - ), - Expanded( - child: MacosScrollbar( - controller: _sidebarScrollController, - child: Padding( - padding: sidebar.padding, - child: sidebar.builder( - context, - _sidebarScrollController, + child: kIsWeb + ? ColoredBox( + color: theme.canvasColor, + child: Column( + children: [ + // If an app is running on macOS, apply + // sidebar.topOffset as needed in order to avoid + // the traffic lights. Otherwise, position the + // sidebar by the top of the application's bounds + // based on the presence of sidebar.top. + if (!kIsWeb && sidebar.topOffset > 0) ...[ + SizedBox(height: sidebar.topOffset), + ] else if (sidebar.top != null) ...[ + const SizedBox(height: 12), + ] else + const SizedBox.shrink(), + if (_sidebarScrollController.hasClients && + _sidebarScrollController.offset > 0.0) + Divider( + thickness: 1, + height: 1, + color: dividerColor), + if (sidebar.top != null && + constraints.maxHeight > 81) + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + ), + child: sidebar.top!, + ), + Expanded( + child: MacosScrollbar( + controller: _sidebarScrollController, + child: Padding( + padding: sidebar.padding, + child: sidebar.builder( + context, + _sidebarScrollController, + ), + ), + ), ), - ), - ), - ), - if (sidebar.bottom != null && - constraints.maxHeight > 141) - Padding( - padding: const EdgeInsets.all(16.0), - child: sidebar.bottom!, - ), - ], - ), - ) : TransparentMacOSSidebar( - state: sidebarState, - child: Column( - children: [ - // If an app is running on macOS, apply - // sidebar.topOffset as needed in order to avoid the - // traffic lights. Otherwise, position the sidebar - // by the top of the application's bounds based on - // the presence of sidebar.top. - if (!kIsWeb && sidebar.topOffset > 0) ...[ - SizedBox(height: sidebar.topOffset), - ] else if (sidebar.top != null) ...[ - const SizedBox(height: 12), - ] else - const SizedBox.shrink(), - if (_sidebarScrollController.hasClients && - _sidebarScrollController.offset > 0.0) - Divider(thickness: 1, height: 1, color: dividerColor), - if (sidebar.top != null && constraints.maxHeight > 81) - Padding( - padding: - const EdgeInsets.symmetric(horizontal: 8.0), - child: sidebar.top!, + if (sidebar.bottom != null && + constraints.maxHeight > 141) + Padding( + padding: const EdgeInsets.all(16.0), + child: sidebar.bottom!, + ), + ], ), - Expanded( - child: MacosScrollbar( - controller: _sidebarScrollController, - child: Padding( - padding: sidebar.padding, - child: sidebar.builder( - context, - _sidebarScrollController, - ), + ) + : TransparentMacOSSidebar( + state: sidebarState, + child: DecoratedBox( + decoration: const BoxDecoration( + color: Color.fromRGBO(0, 0, 0, 1.0), + backgroundBlendMode: BlendMode.clear, + ), + child: Column( + children: [ + // If an app is running on macOS, apply + // sidebar.topOffset as needed in order to avoid + // the traffic lights. Otherwise, position the + // sidebar by the top of the application's bounds + // based on the presence of sidebar.top. + if (!kIsWeb && sidebar.topOffset > 0) ...[ + SizedBox(height: sidebar.topOffset), + ] else if (sidebar.top != null) ...[ + const SizedBox(height: 12), + ] else + const SizedBox.shrink(), + if (_sidebarScrollController.hasClients && + _sidebarScrollController.offset > 0.0) + Divider( + thickness: 1, + height: 1, + color: dividerColor), + if (sidebar.top != null && + constraints.maxHeight > 81) + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + ), + child: sidebar.top!, + ), + Expanded( + child: MacosScrollbar( + controller: _sidebarScrollController, + child: Padding( + padding: sidebar.padding, + child: sidebar.builder( + context, + _sidebarScrollController, + ), + ), + ), + ), + if (sidebar.bottom != null && + constraints.maxHeight > 141) + Padding( + padding: const EdgeInsets.all(16.0), + child: sidebar.bottom!, + ), + ], ), ), ), - if (sidebar.bottom != null && - constraints.maxHeight > 141) - Padding( - padding: const EdgeInsets.all(16.0), - child: sidebar.bottom!, - ), - ], - ), - ), ), ), diff --git a/pubspec.lock b/pubspec.lock index 62a3f534..b2e287b4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -223,18 +223,18 @@ packages: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.15" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.2.0" meta: dependency: transitive description: @@ -364,10 +364,10 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" stack_trace: dependency: transitive description: @@ -456,14 +456,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" - web: - dependency: transitive - description: - name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 - url: "https://pub.dev" - source: hosted - version: "0.1.4-beta" web_socket_channel: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 8d81c2da..983e4bed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: macos_ui description: Flutter widgets and themes implementing the current macOS design language. -version: 2.0.2 +version: 2.0.3 homepage: "https://macosui.dev" repository: "https://github.com/GroovinChip/macos_ui"