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

feat: integrating ask question call to UI #15

Merged
merged 6 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
20 changes: 12 additions & 8 deletions lib/app/view/app.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import 'package:api_client/api_client.dart';
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';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:questions_repository/questions_repository.dart';

class App extends StatelessWidget {
const App({
required this.apiClient,
required this.questionsRepository,
super.key,
});

final ApiClient apiClient;
final QuestionsRepository questionsRepository;

@override
Widget build(BuildContext context) {
return MaterialApp(
theme: VertexTheme.standard,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const HomePage(),
return RepositoryProvider.value(
value: questionsRepository,
child: MaterialApp(
theme: VertexTheme.standard,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: const HomePage(),
),
);
}
}
26 changes: 25 additions & 1 deletion lib/home/bloc/home_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import 'dart:async';

import 'package:api_client/api_client.dart';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:questions_repository/questions_repository.dart';

part 'home_event.dart';
part 'home_state.dart';

class HomeBloc extends Bloc<HomeEvent, HomeState> {
HomeBloc() : super(const HomeState()) {
HomeBloc(this._questionsRepository) : super(const HomeState()) {
on<FromWelcomeToQuestion>(_onFromWelcomeToQuestion);
on<AskQuestion>(_onQuestion);
on<QueryUpdated>(_queryUpdated);
on<QuestionAsked>(_questionAsked);
}

final QuestionsRepository _questionsRepository;

Future<void> _onFromWelcomeToQuestion(
FromWelcomeToQuestion event,
Emitter<HomeState> emit,
Expand All @@ -25,4 +31,22 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
) async {
emit(state.copyWith(status: Status.askQuestion));
}

FutureOr<void> _queryUpdated(QueryUpdated event, Emitter<HomeState> emit) {
omartinma marked this conversation as resolved.
Show resolved Hide resolved
emit(state.copyWith(query: event.query));
}

Future<FutureOr<void>> _questionAsked(
omartinma marked this conversation as resolved.
Show resolved Hide resolved
QuestionAsked event,
Emitter<HomeState> emit,
) async {
emit(state.copyWith(status: Status.askQuestionToThinking));
final result = await _questionsRepository.getVertexResponse(state.query);
emit(
state.copyWith(
status: Status.thinkingToResults,
vertexResponse: result,
),
);
}
}
15 changes: 15 additions & 0 deletions lib/home/bloc/home_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,18 @@ class FromWelcomeToQuestion extends HomeEvent {
class AskQuestion extends HomeEvent {
const AskQuestion();
}

class QueryUpdated extends HomeEvent {
const QueryUpdated({required this.query});

final String query;
@override
List<Object> get props => [query];
}

class QuestionAsked extends HomeEvent {
const QuestionAsked();

@override
List<Object> get props => [];
omartinma marked this conversation as resolved.
Show resolved Hide resolved
}
24 changes: 22 additions & 2 deletions lib/home/bloc/home_state.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,47 @@
part of 'home_bloc.dart';

enum Status { welcome, welcomeToAskQuestion, askQuestion }
enum Status {
welcome,
welcomeToAskQuestion,
askQuestion,
askQuestionToThinking,
thinking,
thinkingToResults,
results,
}

class HomeState extends Equatable {
const HomeState({
this.status = Status.welcome,
this.query = '',
this.vertexResponse = const VertexResponse.empty(),
});

final Status status;
final String query;
final VertexResponse vertexResponse;

bool get isWelcomeVisible =>
status == Status.welcome || status == Status.welcomeToAskQuestion;
bool get isQuestionVisible =>
status == Status.welcomeToAskQuestion || status == Status.askQuestion;
bool get isThinkingVisible =>
status == Status.askQuestionToThinking || status == Status.thinking;
bool get isResultsVisible =>
status == Status.thinkingToResults || status == Status.results;

HomeState copyWith({
Status? status,
String? query,
VertexResponse? vertexResponse,
}) {
return HomeState(
status: status ?? this.status,
query: query ?? this.query,
vertexResponse: vertexResponse ?? this.vertexResponse,
);
}

@override
List<Object> get props => [status];
List<Object> get props => [status, query, vertexResponse];
}
5 changes: 4 additions & 1 deletion lib/home/view/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import 'package:app_ui/app_ui.dart';
import 'package:dash_ai_search/home/home.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:questions_repository/questions_repository.dart';

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

@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => HomeBloc(),
create: (_) => HomeBloc(context.read<QuestionsRepository>()),
child: const HomeView(),
);
}
Expand Down Expand Up @@ -39,6 +40,8 @@ class HomeView extends StatelessWidget {
),
if (state.isWelcomeVisible) const WelcomeView(),
if (state.isQuestionVisible) const QuestionView(),
if (state.isThinkingVisible) const ThinkingView(),
if (state.isResultsVisible) const ResultsView(),
const Positioned(
bottom: 50,
left: 50,
Expand Down
6 changes: 6 additions & 0 deletions lib/home/widgets/question_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ class QuestionView extends StatelessWidget {
icon: vertexIcons.stars.image(),
hint: l10n.questionHint,
actionText: l10n.ask,
onTextUpdated: (String query) {
context.read<HomeBloc>().add(QueryUpdated(query: query));
},
onActionPressed: () {
context.read<HomeBloc>().add(const QuestionAsked());
},
),
],
),
Expand Down
26 changes: 26 additions & 0 deletions lib/home/widgets/results_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:app_ui/app_ui.dart';
import 'package:dash_ai_search/home/home.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

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

@override
Widget build(BuildContext context) {
final response =
context.select((HomeBloc bloc) => bloc.state.vertexResponse);
return Center(
child: Container(
color: VertexColors.googleBlue,
width: 200,
constraints: const BoxConstraints(minWidth: 500, maxHeight: 700),
padding: const EdgeInsets.symmetric(horizontal: 48, vertical: 64),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [Text(response.summary)],
),
),
);
}
}
41 changes: 41 additions & 0 deletions lib/home/widgets/thinking_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import 'package:dash_ai_search/home/home.dart';
import 'package:dash_ai_search/l10n/l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

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

@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 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,
),
],
),
),
),
);
}
}
2 changes: 2 additions & 0 deletions lib/home/widgets/widgets.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export 'background.dart';
export 'logo.dart';
export 'question_view.dart';
export 'results_view.dart';
export 'thinking_view.dart';
export 'welcome_view.dart';
4 changes: 4 additions & 0 deletions lib/l10n/arb/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,9 @@
"ask": "Ask",
"@ask": {
"description": "Button text for ask"
},
"thinkingHeadline": "Getting answers for",
"@thinkingHeadline": {
"description": "Headline on thinking screen"
}
}
6 changes: 5 additions & 1 deletion lib/main_development.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:api_client/api_client.dart';
import 'package:dash_ai_search/app/app.dart';
import 'package:dash_ai_search/bootstrap.dart';
import 'package:questions_repository/questions_repository.dart';

void main() {
bootstrap(
Expand All @@ -9,8 +10,11 @@ void main() {
baseUrl: 'http://development',
);

final questionsRepository =
QuestionsRepository(apiClient.questionsResource);

return App(
apiClient: apiClient,
questionsRepository: questionsRepository,
);
},
);
Expand Down
6 changes: 5 additions & 1 deletion lib/main_production.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:api_client/api_client.dart';
import 'package:dash_ai_search/app/app.dart';
import 'package:dash_ai_search/bootstrap.dart';
import 'package:questions_repository/questions_repository.dart';

void main() {
bootstrap(
Expand All @@ -9,8 +10,11 @@ void main() {
baseUrl: 'http://production',
);

final questionsRepository =
QuestionsRepository(apiClient.questionsResource);

return App(
apiClient: apiClient,
questionsRepository: questionsRepository,
);
},
);
Expand Down
2 changes: 1 addition & 1 deletion packages/api_client/lib/src/models/vertex_metadata.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class VertexMetadata extends Equatable {
final String title;

/// Description
final String description;
final String? description;

@override
List<Object?> get props => [url, title, description];
Expand Down
2 changes: 1 addition & 1 deletion packages/api_client/lib/src/models/vertex_metadata.g.dart

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

4 changes: 3 additions & 1 deletion packages/api_client/lib/src/models/vertex_response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ part 'vertex_response.g.dart';
@JsonSerializable()
class VertexResponse extends Equatable {
/// {@macro vertex_response}

const VertexResponse({
required this.summary,
required this.documents,
});

/// {@macro vertex_response}
const VertexResponse.empty({this.summary = '', this.documents = const []});

/// Convert from Map<String, dynamic> to [VertexResponse]
factory VertexResponse.fromJson(Map<String, dynamic> json) =>
_$VertexResponseFromJson(json);
Expand Down
Loading