Skip to content

Commit

Permalink
feat(app): add candle effect
Browse files Browse the repository at this point in the history
  • Loading branch information
davidgomesdev committed Jan 14, 2024
1 parent c315e3e commit 88ed259
Show file tree
Hide file tree
Showing 9 changed files with 320 additions and 12 deletions.
36 changes: 36 additions & 0 deletions app/lib/bloc/effects/candle_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import 'package:rusty_controller/bloc/specific_effect_bloc.dart';
import 'package:rusty_controller/model/led_effects.dart';

class CandleBloc
extends SpecificEffectBloc<CandleEffectEvent, CandleLedEffect> {
CandleBloc(super.effect) {
on<CandleEffectEvent>((event, emit) => emit(event.toEffect(state)));
}
}

class CandleEffectEvent {
double? hue;
double? saturation;
double? minValue;
double? maxValue;
double? variability;
int? interval;

CandleEffectEvent(
{this.hue,
this.saturation,
this.minValue,
this.maxValue,
this.variability,
this.interval});

CandleLedEffect toEffect(CandleLedEffect currentEffect) {
return CandleLedEffect(
hue: hue ?? currentEffect.hue,
saturation: saturation ?? currentEffect.saturation,
minValue: minValue ?? currentEffect.minValue,
maxValue: maxValue ?? currentEffect.maxValue,
variability: variability ?? currentEffect.variability,
interval: interval ?? currentEffect.interval);
}
}
31 changes: 26 additions & 5 deletions app/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:logger/logger.dart';
import 'package:rusty_controller/bloc/discovery_bloc.dart';
import 'package:rusty_controller/bloc/effect_bloc.dart';
import 'package:rusty_controller/bloc/effects/breathing_bloc.dart';
import 'package:rusty_controller/bloc/effects/candle_bloc.dart';
import 'package:rusty_controller/bloc/effects/rainbow_bloc.dart';
import 'package:rusty_controller/bloc/effects/static_bloc.dart';
import 'package:rusty_controller/extensions/color_extensions.dart';
Expand All @@ -22,12 +23,24 @@ final defaultEffects = {
EffectType.off: OffLedEffect(),
EffectType.static: StaticLedEffect(color: Colors.black.toHSV()),
EffectType.breathing: BreathingLedEffect(
color: Colors.red.toHSV().withValue(0.0),
timeToPeak: maxBreathingTime,
peak: 1.0,
breatheFromOff: true),
color: Colors.red.toHSV().withValue(0.0),
timeToPeak: maxBreathingTime,
peak: 1.0,
breatheFromOff: true,
),
EffectType.candle: CandleLedEffect(
hue: 0,
saturation: 1.0,
minValue: 0.5,
maxValue: 0.8,
variability: 1.0,
interval: 100,
),
EffectType.rainbow: RainbowLedEffect(
saturation: 1.0, value: 0.5, timeToComplete: maxRainbowTime),
saturation: 1.0,
value: 0.5,
timeToComplete: maxRainbowTime,
),
};

void main() {
Expand Down Expand Up @@ -78,6 +91,14 @@ void setupDependencies() {
return BreathingBloc(savedBreathing);
},
);
serviceLocator.registerSingletonAsync(
() async {
final savedCandle = await storeService.get<CandleLedEffect>(
defaultValue: defaultEffects[EffectType.candle] as CandleLedEffect);

return CandleBloc(savedCandle);
},
);
serviceLocator.registerSingletonAsync(
() async {
final savedRainbow = await storeService.get<RainbowLedEffect>(
Expand Down
75 changes: 73 additions & 2 deletions app/lib/model/led_effects.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/painting.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:rusty_controller/model/util/json_converters.dart';
import 'package:rusty_controller/service/store_service.dart';

part 'led_effects.g.dart';

abstract class LedEffect {
abstract class LedEffect extends Equatable {
EffectType get type;

String get name => type.name;
Expand All @@ -17,7 +18,7 @@ abstract class LedEffect {
Map<String, dynamic> get graphqlVariables;
}

enum EffectType { none, off, static, breathing, rainbow }
enum EffectType { none, off, static, breathing, candle, rainbow }

// A placeholder/null-object pattern for when there's no effect selected,
// while avoiding null-checks
Expand All @@ -33,6 +34,9 @@ class NoLedEffect extends LedEffect {

@override
Map<String, dynamic> get graphqlVariables => {};

@override
List<Object?> get props => [];
}

class OffLedEffect extends LedEffect {
Expand All @@ -51,6 +55,9 @@ class OffLedEffect extends LedEffect {

@override
Map<String, dynamic> get graphqlVariables => {};

@override
List<Object?> get props => [];
}

@JsonSerializable()
Expand Down Expand Up @@ -89,6 +96,9 @@ class StaticLedEffect extends LedEffect implements StorableObject {

@override
Map<String, dynamic> toJson() => _$StaticLedEffectToJson(this);

@override
List<Object?> get props => [color];
}

@JsonSerializable()
Expand Down Expand Up @@ -136,6 +146,64 @@ class BreathingLedEffect extends LedEffect implements StorableObject {

@override
Map<String, dynamic> toJson() => _$BreathingLedEffectToJson(this);

@override
List<Object?> get props => [color, timeToPeak, peak, breatheFromOff];
}

@JsonSerializable()
@HSVColorJsonConverter()
class CandleLedEffect extends LedEffect implements StorableObject {
@override
EffectType get type => EffectType.candle;

final double hue;
final double saturation;
final double minValue;
final double maxValue;
final double variability;
final int interval;

CandleLedEffect(
{required this.hue,
required this.saturation,
required this.minValue,
required this.maxValue,
required this.variability,
required this.interval});

@override
String get graphqlMutation => """
mutation SetLedCandle(\$input: CandleLedEffectInput!) {
setLedCandle(input: \$input)
}
""";

@override
String get graphqlMutationName => "setLedCandle";

@override
Map<String, dynamic> get graphqlVariables => {
"hue": hue.round(),
"saturation": saturation,
"minValue": minValue,
"maxValue": maxValue,
"variability": variability,
"interval": interval
};

@override
String get storeName => "candle";

@override
CandleLedEffect fromJson(Map<String, dynamic> json) =>
_$CandleLedEffectFromJson(json);

@override
Map<String, dynamic> toJson() => _$CandleLedEffectToJson(this);

@override
List<Object?> get props => [hue, saturation, minValue, maxValue, variability, interval];
}

@JsonSerializable()
Expand Down Expand Up @@ -178,4 +246,7 @@ class RainbowLedEffect extends LedEffect implements StorableObject {

@override
Map<String, dynamic> toJson() => _$RainbowLedEffectToJson(this);

@override
List<Object?> get props => [saturation, value, timeToComplete];
}
28 changes: 24 additions & 4 deletions app/lib/model/led_effects.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

74 changes: 74 additions & 0 deletions app/lib/widgets/effect_settings/candle_settings.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:rusty_controller/bloc/effects/candle_bloc.dart';
import 'package:rusty_controller/main.dart';
import 'package:rusty_controller/model/led_effects.dart';
import 'package:rusty_controller/widgets/effect_settings/common/labeled_slider.dart';

class CandleSettings extends StatelessWidget {
final initialColor = const HSVColor.fromAHSV(1.0, 0.0, 1.0, 1.0);

const CandleSettings({super.key});

@override
Widget build(BuildContext context) {
final bloc = serviceLocator.get<CandleBloc>();
return BlocBuilder<CandleBloc, CandleLedEffect>(
bloc: bloc,
builder: (ctx, effect) {
final color = initialColor.withHue(effect.hue);

return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: Padding(
padding: EdgeInsets.only(bottom: 48.0),
child: Stack(
alignment: Alignment.center,
children: [
ColorIndicator(color, width: 60.0, height: 60.0),
SizedBox(
width: 200,
height: 200,
child: ColorPickerHueRing(
color,
displayThumbColor: false,
strokeWidth: 30.0,
(color) {
bloc.add(CandleEffectEvent(hue: color.hue));
},
),
)
],
),
),
),
Column(
children: [
LabeledRangeSlider(
onChanged: (min, max) {
bloc.add(CandleEffectEvent(minValue: min, maxValue: max));
},
label: "Brightness range",
start: effect.minValue,
end: effect.maxValue,
),
LabeledSlider(
onChanged: (interval) {
bloc.add(CandleEffectEvent(interval: interval.toInt()));
},
label: "Interval",
value: effect.interval.toDouble(),
min: 100,
max: 800,
),
],
),
],
);
},
);
}
}
Loading

0 comments on commit 88ed259

Please sign in to comment.