Skip to content

Commit

Permalink
PAINTROID-455 Add Color Picker (#40)
Browse files Browse the repository at this point in the history
* Add Color Picker

* Implement color picker

* Fix issues

* Merge with develop

* Fix issues

* Resolve pubspec errors

* address requested changes

* fix minor issues

* refactoring and minor fixes

* use checkerboardimg from component_library

* fix minor issues

* revert app_localizations file

* add dynamic color change, separate colorpicker package

* use riverpod generator

* fix lint errors

* add tests

* fix riverpod issues, remove redundancies

* remove comments, capitalize text

* convert stateful to stateless, rename widgets

* address changes, remove slider position state provider

* fix minor issues

* debug test error

* Revert "debug test error"

This reverts commit e8a6e03.

* debug test error

* fix test error

* resolve conflicts

* sort imports, remove duplicates

* fix lint errors

* use paintroid theme colors

* fix minor issues

* fix lint errors

* fix background color

* fix test error, minor refactoring

* minor fixes

* fix pubspec.lock

* update makefile to run pub get in packages

* minor changes

* fix dependency
  • Loading branch information
bhav-khurana authored Aug 16, 2024
1 parent 17577d1 commit ae20a51
Show file tree
Hide file tree
Showing 29 changed files with 939 additions and 170 deletions.
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ FVM_PRESENT := $(shell command -v fvm 2> /dev/null)
# Use fvm if installed; otherwise use flutter directly
FLUTTER_CMD := $(if $(FVM_PRESENT),fvm flutter,flutter)
DART_CMD := $(if $(FVM_PRESENT),fvm dart,dart)
PACKAGES_DIR := packages

INTEGRATION_TEST_DIR=test/integration
DRIVER_FILE=$(INTEGRATION_TEST_DIR)/driver/driver.dart
Expand All @@ -17,9 +18,15 @@ endif

clean:
$(FLUTTER_CMD) clean

get:
$(FLUTTER_CMD) pub get
@for dir in $(shell find $(PACKAGES_DIR) -maxdepth 1 -type d); do \
if [ "$$dir" != "$(PACKAGES_DIR)" ]; then \
echo "Running $(FLUTTER_CMD) pub get in $$dir"; \
(cd $$dir && $(FLUTTER_CMD) pub get); \
fi \
done

run:
$(FLUTTER_CMD) run
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/pages/landing_page/components/project_list_tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:paintroid/core/models/database/project.dart';
import 'package:paintroid/core/providers/object/image_service.dart';
import 'package:paintroid/ui/pages/landing_page/components/image_preview.dart';
import 'package:paintroid/ui/pages/landing_page/components/project_overflow_menu.dart';
import 'package:paintroid/ui/theme/theme.dart';

class ProjectListTile extends StatelessWidget {
final Project project;
Expand All @@ -31,7 +32,7 @@ class ProjectListTile extends StatelessWidget {
project: project,
imageService: imageService,
width: 80,
color: Colors.white,
color: PaintroidTheme.of(context).onSurfaceColor,
),
dense: false,
title: Text(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'package:flutter/material.dart';

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:colorpicker/colorpicker.dart';

import 'package:paintroid/core/enums/tool_types.dart';
import 'package:paintroid/core/localization/app_localizations.dart';
import 'package:paintroid/core/providers/state/paint_provider.dart';
import 'package:paintroid/core/providers/state/tool_options_visibility_state_provider.dart';
import 'package:paintroid/core/providers/state/toolbox_state_provider.dart';
import 'package:paintroid/core/tools/tool_data.dart';
Expand All @@ -21,6 +23,7 @@ class BottomNavBar extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final localizations = AppLocalizations.of(context);
final currentToolData = getCurrentToolData(ref);
final currentPaint = ref.watch(paintProvider);

return NavigationBarTheme(
data: PaintroidTheme.of(context).bottomNavBarThemeData,
Expand All @@ -40,10 +43,19 @@ class BottomNavBar extends ConsumerWidget {
),
NavigationDestination(
label: localizations.color,
icon: Icon(
Icons.check_box_outline_blank,
size: 24,
color: PaintroidTheme.of(context).onSurfaceColor,
icon: InkWell(
child: Container(
height: 24.0,
width: 24.0,
decoration: BoxDecoration(
color: currentPaint.color,
border: Border.all(
color: PaintroidTheme.of(context).onSurfaceColor,
width: 1.4,
),
borderRadius: BorderRadius.circular(2.0),
),
),
),
),
NavigationDestination(
Expand Down Expand Up @@ -77,6 +89,9 @@ void _onNavigationItemSelected(int index, BuildContext context, WidgetRef ref) {
case BottomNavBarItem.TOOL_OPTIONS:
_handleToolOptionsVisibility(ref);
break;
case BottomNavBarItem.COLOR:
_showColorPicker(context, ref);
break;
default:
return;
}
Expand All @@ -96,3 +111,26 @@ void _showToolBottomSheet(BuildContext context) {
void _handleToolOptionsVisibility(WidgetRef ref) {
ref.read(toolOptionsVisibilityStateProvider.notifier).toggleVisibility();
}

void _showColorPicker(BuildContext context, WidgetRef ref) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (BuildContext dialogContext) => Container(
height: MediaQuery.of(dialogContext).size.height * 0.7,
alignment: Alignment.center,
decoration: BoxDecoration(
color: PaintroidTheme.of(dialogContext).onSurfaceColor,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(16.0),
topRight: Radius.circular(16.0),
)),
child: ColorPicker(
currentColor: ref.watch(paintProvider).color,
onColorChanged: (newColor) {
ref.watch(paintProvider.notifier).updateColor(newColor);
},
),
),
);
}
2 changes: 2 additions & 0 deletions lib/ui/theme/data/custom_colors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ abstract class CustomColors {
static const darkCharcoal = Color(0xFF191C1D);
static const deepCharcoal = Color(0xFF191C1D);
static const jetBlack = Color(0xFF000000);

static const transparentColor = Color(0x00000000);
}

extension ToMaterialColor on Color {
Expand Down
3 changes: 3 additions & 0 deletions lib/ui/theme/data/dark_paintroid_theme_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ class DarkPaintroidThemeData extends PaintroidThemeData {
@override
Color get tertiaryContainerColor => CustomColors.deepAqua;

@override
Color get transparentColor => CustomColors.transparentColor;

@override
TextStyle get titleStyle => const TextStyle(
color: CustomColors.pureWhite,
Expand Down
3 changes: 3 additions & 0 deletions lib/ui/theme/data/light_paintroid_theme_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ class LightPaintroidThemeData extends PaintroidThemeData {
@override
Color get tertiaryContainerColor => CustomColors.deepAqua;

@override
Color get transparentColor => CustomColors.transparentColor;

@override
TextStyle get titleStyle => const TextStyle(
color: CustomColors.pureWhite,
Expand Down
1 change: 1 addition & 0 deletions lib/ui/theme/data/paintroid_theme_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ abstract class PaintroidThemeData {
Color get shadowColor;

Color get surfaceTintColor;
Color get transparentColor;

Color get scaffoldBackgroundColor;

Expand Down
10 changes: 10 additions & 0 deletions packages/colorpicker/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: "9e1c857886f07d342cf106f2cd588bcd5e031bb2"
channel: "stable"

project_type: package
23 changes: 23 additions & 0 deletions packages/colorpicker/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
include: package:flutter_lints/flutter.yaml
linter:
rules:
always_use_package_imports: true
avoid_relative_lib_imports: true
prefer_relative_imports: false
prefer_single_quotes: true
avoid_void_async: true
constant_identifier_names: false

analyzer:
errors:
missing_enum_constant_in_switch: error
exhaustive_cases: error
unused_element: error
type_annotate_public_apis: error
missing_required_param: error
invalid_use_of_protected_member: error
unused_import: error

exclude:
- lib/src/**.pb*.dart
- lib/src/data/*.g.dart
Binary file added packages/colorpicker/assets/img/checkerboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions packages/colorpicker/lib/colorpicker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
library colorpicker;

export 'src/colorpicker.dart';
export 'src/constants/colors.dart';
export 'src/components/color_comparison.dart';
export 'src/components/opacity_slider.dart';
export 'src/components/slider_indicator_shape.dart';
95 changes: 95 additions & 0 deletions packages/colorpicker/lib/src/colorpicker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import 'package:colorpicker/src/components/checkerboard_square.dart';
import 'package:colorpicker/src/components/color_square.dart';
import 'package:colorpicker/src/constants/colors.dart';
import 'package:colorpicker/src/components/color_comparison.dart';
import 'package:colorpicker/src/components/opacity_slider.dart';
import 'package:colorpicker/src/state/color_picker_state_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class ColorPicker extends ConsumerWidget {
const ColorPicker({
super.key,
required this.currentColor,
required this.onColorChanged,
});

final Color currentColor;
final void Function(Color) onColorChanged;

final colors = DisplayColors.colors;

@override
Widget build(BuildContext context, WidgetRef ref) {
final colorPickerStateData = ref.watch(colorPickerStateProvider);
return Container(
margin: const EdgeInsets.all(26.0),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16.0),
),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ColorComparison(
currentColor: currentColor,
newColor: colorPickerStateData.currentColor != null
? colorPickerStateData.currentColor!.withOpacity(
colorPickerStateData.currentOpacity,
)
: currentColor,
),
const SizedBox(height: 10.0),
GridView.count(
childAspectRatio: 1.4,
crossAxisCount: 4,
crossAxisSpacing: 2.0,
mainAxisSpacing: 2.0,
shrinkWrap: true,
children: List.generate(
colors.length + 1,
(index) {
if (index == colors.length) {
return const CheckerboardSquare();
} else {
return ColorSquare(color: colors[index]);
}
},
),
),
const SizedBox(height: 20.0),
OpacitySlider(
gradientColor: colorPickerStateData.currentColor != null
? colorPickerStateData.currentColor!
: currentColor,
),
const SizedBox(height: 20.0),
Row(
children: [
const Spacer(),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('CANCEL'),
),
const SizedBox(width: 10.0),
TextButton(
onPressed: () {
if (colorPickerStateData.currentColor != null) {
onColorChanged(colorPickerStateData.currentColor!
.withOpacity(colorPickerStateData.currentOpacity));
}
Navigator.pop(context);
},
child: const Text('APPLY'),
),
],
)
],
),
),
);
}
}
19 changes: 19 additions & 0 deletions packages/colorpicker/lib/src/components/checkerboard_square.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:colorpicker/utils/assets.dart';
import 'package:flutter/material.dart';

class CheckerboardSquare extends StatelessWidget {
const CheckerboardSquare({super.key});

@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: PackageAssets.getCheckerboardImgAsset(),
fit: BoxFit.contain,
repeat: ImageRepeat.repeat,
),
),
);
}
}
76 changes: 76 additions & 0 deletions packages/colorpicker/lib/src/components/color_comparison.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import 'package:colorpicker/utils/assets.dart';
import 'package:flutter/material.dart';

class ColorComparison extends StatelessWidget {
const ColorComparison({
super.key,
required this.currentColor,
required this.newColor,
});

final Color currentColor;
final Color newColor;

@override
Widget build(BuildContext context) {
return SizedBox(
width: 130.0,
height: 70.0,
child: Row(
children: [
Expanded(
child: ColorDescription(
color: currentColor,
description: 'current',
),
),
Expanded(
child: ColorDescription(
color: newColor,
description: 'new',
),
),
],
),
);
}
}

class ColorDescription extends StatelessWidget {
const ColorDescription({
super.key,
required this.color,
required this.description,
});

final Color color;
final String description;

@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: PackageAssets.getCheckerboardImgAsset(),
repeat: ImageRepeat.repeat,
),
),
child: Container(
decoration: BoxDecoration(
color: color,
),
),
),
),
const SizedBox(width: 8.0),
Text(
description,
style: const TextStyle(color: Color.fromARGB(255, 149, 149, 149)),
),
],
);
}
}
Loading

0 comments on commit ae20a51

Please sign in to comment.