Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

feat: thinking screen basic UI #16

Merged
merged 1 commit into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/home/bloc/home_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ class HomeState extends Equatable {
status == Status.askQuestionToThinking || status == Status.thinking;
bool get isResultsVisible =>
status == Status.thinkingToResults || status == Status.results;
bool get isDashVisible => [
Status.welcome,
Status.welcomeToAskQuestion,
Status.askQuestion,
Status.askQuestionToThinking,
Status.thinkingToResults,
Status.results,
].contains(status);

HomeState copyWith({
Status? status,
Expand Down
22 changes: 12 additions & 10 deletions lib/home/view/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ class HomeView extends StatelessWidget {
backgroundColor: VertexColors.arctic,
body: Stack(
children: [
const Positioned(
top: 0,
bottom: 0,
child: Background(),
),
if (state.isWelcomeVisible)
const Positioned(
top: 0,
bottom: 0,
child: Background(),
),
const Positioned(
top: 40,
left: 48,
Expand All @@ -42,11 +43,12 @@ class HomeView extends StatelessWidget {
if (state.isQuestionVisible) const QuestionView(),
if (state.isThinkingVisible) const ThinkingView(),
if (state.isResultsVisible) const ResultsView(),
const Positioned(
bottom: 50,
left: 50,
child: DashAnimation(),
),
if (state.isDashVisible)
const Positioned(
bottom: 50,
left: 50,
child: DashAnimation(),
),
],
),
);
Expand Down
97 changes: 1 addition & 96 deletions lib/home/widgets/background.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:app_ui/app_ui.dart';
import 'package:dash_ai_search/home/home.dart';
import 'package:flutter/material.dart';
import 'package:path_drawing/path_drawing.dart';

class Background extends StatelessWidget {
const Background({super.key});
Expand Down Expand Up @@ -45,98 +45,3 @@ class Background extends StatelessWidget {
);
}
}

class Circle extends StatelessWidget {
@visibleForTesting
const Circle({
this.offset = Offset.zero,
this.radius = 303,
this.borderColor = VertexColors.white,
this.dotted = false,
this.child,
super.key,
});

final Offset offset;
final double radius;
final Color borderColor;
final bool dotted;
final Widget? child;

@override
Widget build(BuildContext context) {
return CustomPaint(
painter: CirclePainter(
offset: offset,
radius: radius,
borderColor: borderColor,
dotted: dotted,
),
child: child,
);
}
}

class CirclePainter extends CustomPainter {
CirclePainter({
required this.offset,
required this.radius,
required this.borderColor,
required this.dotted,
}) {
_paintCircle = Paint()
..color = VertexColors.white
..style = PaintingStyle.fill;
_paintBorder = Paint()
..color = borderColor
..strokeWidth = 2
..strokeCap = StrokeCap.butt
..style = PaintingStyle.stroke;
}

final Offset offset;
final double radius;
final Color borderColor;
final bool dotted;

late final Paint _paintCircle;
late final Paint _paintBorder;

@override
void paint(Canvas canvas, Size size) {
canvas.drawCircle(
offset,
radius,
_paintCircle,
);

if (dotted) {
const dashPattern = <double>[4, 4];
final s = radius * 2;

var path = Path()
..addRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(
offset.dx - s / 2,
offset.dy / 2 - s / 2,
s,
s,
),
Radius.circular(s / 2),
),
);
path = dashPath(path, dashArray: CircularIntervalList(dashPattern));
canvas.drawPath(path, _paintBorder);
} else {
canvas.drawCircle(
offset,
radius,
_paintBorder,
);
}
}

@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
103 changes: 103 additions & 0 deletions lib/home/widgets/circle.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import 'package:app_ui/app_ui.dart';
import 'package:flutter/widgets.dart';
import 'package:path_drawing/path_drawing.dart';

class Circle extends StatelessWidget {
const Circle({
this.offset = Offset.zero,
this.radius = 303,
this.borderColor = VertexColors.white,
this.dotted = false,
this.child,
this.backgroundColor = VertexColors.white,
super.key,
});

final Offset offset;
final double radius;
final Color borderColor;
final bool dotted;
final Widget? child;
final Color backgroundColor;

@override
Widget build(BuildContext context) {
return CustomPaint(
painter: CirclePainter(
offset: offset,
radius: radius,
borderColor: borderColor,
dotted: dotted,
backgroundColor: backgroundColor,
),
child: child,
);
}
}

class CirclePainter extends CustomPainter {
@visibleForTesting
CirclePainter({
required this.offset,
required this.radius,
required this.borderColor,
required this.dotted,
required this.backgroundColor,
}) {
_paintCircle = Paint()
..color = backgroundColor
..style = PaintingStyle.fill;
_paintBorder = Paint()
..color = borderColor
..strokeWidth = 2
..strokeCap = StrokeCap.butt
..style = PaintingStyle.stroke;
}

final Offset offset;
final double radius;
final Color borderColor;
final bool dotted;
final Color backgroundColor;

late final Paint _paintCircle;
late final Paint _paintBorder;

@override
void paint(Canvas canvas, Size size) {
canvas.drawCircle(
offset,
radius,
_paintCircle,
);

if (dotted) {
const dashPattern = <double>[4, 4];
final s = radius * 2;

var path = Path()
..addRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(
offset.dx - s / 2,
offset.dy / 2 - s / 2,
s,
s,
),
Radius.circular(s / 2),
),
);
path = dashPath(path, dashArray: CircularIntervalList(dashPattern));
canvas.drawPath(path, _paintBorder);
} else {
canvas.drawCircle(
offset,
radius,
_paintBorder,
);
}
}

@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
99 changes: 77 additions & 22 deletions lib/home/widgets/thinking_view.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:app_ui/app_ui.dart';
import 'package:dash_ai_search/home/home.dart';
import 'package:dash_ai_search/l10n/l10n.dart';
import 'package:flutter/material.dart';
Expand All @@ -8,34 +9,88 @@ class ThinkingView extends StatelessWidget {

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

final state = context.watch<HomeBloc>().state;
final isAnimating = state.status == Status.askQuestionToThinking;
final isAnimating = context.select(
(HomeBloc bloc) => bloc.state.status == Status.askQuestionToThinking,
);
final query = context.select((HomeBloc bloc) => bloc.state.query);
return AnimatedOpacity(
opacity: isAnimating ? 1 : 0,
duration: const Duration(milliseconds: 500),
child: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
l10n.thinkingHeadline,
textAlign: TextAlign.center,
style: theme.textTheme.bodyMedium,
),
Text(
query,
textAlign: TextAlign.center,
style: theme.textTheme.headlineLarge,
),
],
child: Stack(
children: [
const Align(child: Circles()),
Align(
child: TextArea(query: query),
),
),
],
),
);
}
}

class TextArea extends StatelessWidget {
@visibleForTesting
const TextArea({required this.query, super.key});

final String query;

@override
Widget build(BuildContext context) {
final l10n = context.l10n;

return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
l10n.thinkingHeadline,
textAlign: TextAlign.center,
style:
VertexTextStyles.body.copyWith(color: VertexColors.flutterNavy),
),
const SizedBox(
height: 40,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 300),
child: Text(
query,
textAlign: TextAlign.center,
style: VertexTextStyles.display,
),
),
],
);
}
}

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

@override
Widget build(BuildContext context) {
const backgroundColor = Colors.transparent;
const borderColor = VertexColors.googleBlue;
return const Stack(
children: [
Circle(
dotted: true,
backgroundColor: backgroundColor,
borderColor: borderColor,
radius: 162,
),
Circle(
dotted: true,
backgroundColor: backgroundColor,
borderColor: borderColor,
radius: 353,
),
Circle(
dotted: true,
backgroundColor: backgroundColor,
borderColor: borderColor,
radius: 590,
),
],
);
}
}
1 change: 1 addition & 0 deletions lib/home/widgets/widgets.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export 'background.dart';
export 'circle.dart';
export 'logo.dart';
export 'question_view.dart';
export 'results_view.dart';
Expand Down
3 changes: 3 additions & 0 deletions packages/app_ui/lib/src/colors/vertex_colors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ abstract class VertexColors {
/// Navy Color Swatch
static const Color navy = Color(0xff020f30);

/// Fluter Navy Color Swatch
static const Color flutterNavy = Color(0xff042A59);
omartinma marked this conversation as resolved.
Show resolved Hide resolved

/// Google Blue Color Swatch
static const Color googleBlue = Color(0xff3089f1);

Expand Down
Loading