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

fix: summary jump #56

Merged
merged 3 commits into from
Dec 1, 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
168 changes: 107 additions & 61 deletions lib/home/widgets/results_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class SearchBoxViewState extends State<SearchBoxView>
Widget build(BuildContext context) {
return Container(
constraints: const BoxConstraints(
maxWidth: 595,
maxWidth: 659,
),
child: SlideTransition(
position: _offset,
Expand Down Expand Up @@ -253,7 +253,7 @@ class BlueContainerState extends State<BlueContainer>

void _initSizeIn() {
sizeIn = Tween<Size>(
begin: const Size(600, 700),
begin: const Size(659, 732),
end: Size(
widget.constraints.maxWidth,
widget.constraints.maxHeight,
Expand Down Expand Up @@ -322,12 +322,12 @@ class _AiResponseState extends State<_AiResponse>

enterTransitionController = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
duration: const Duration(seconds: 2),
);

exitTransitionController = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
duration: const Duration(milliseconds: 800),
);
}

Expand Down Expand Up @@ -429,76 +429,122 @@ class _AiResponseState extends State<_AiResponse>
}
}

class SummaryView extends StatelessWidget {
class SummaryView extends StatefulWidget {
const SummaryView({
super.key,
});

@override
State<SummaryView> createState() => _SummaryViewState();
}

class _SummaryViewState extends State<SummaryView>
with TickerProviderStateMixin, TransitionScreenMixin {
late Animation<double> _width;

@override
List<Status> get forwardExitStatuses => [Status.resultsToSourceAnswers];

@override
List<Status> get backEnterStatuses => [Status.sourceAnswersBackToResults];

@override
void initializeTransitionController() {
super.initializeTransitionController();

enterTransitionController = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);

exitTransitionController = AnimationController(
vsync: this,
duration: const Duration(seconds: 1),
);
}

@override
void initState() {
super.initState();

_width = Tween<double>(begin: 563, end: 659).animate(
CurvedAnimation(
parent: exitTransitionController,
curve: Curves.decelerate,
),
);
}

@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
final parsed = context.select((HomeBloc bloc) => bloc.state.parsedSummary);

return SizedBox(
width: 540,
child: RichText(
text: TextSpan(
children: [
for (final element in parsed.elements)
if (element.isLink)
WidgetSpan(
child: InkWell(
onTap: () {
final isOnSeeSourceAnswers =
context.read<HomeBloc>().state.status ==
Status.seeSourceAnswers;
if (isOnSeeSourceAnswers) {
context.read<HomeBloc>().add(
NavigateSourceAnswers(
element.text,
),
);
} else {
context.read<HomeBloc>().add(
SeeSourceAnswersRequested(
element.text,
),
);
}
},
child: Container(
margin: const EdgeInsets.symmetric(
horizontal: 2,
),
padding: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 12,
),
decoration: const BoxDecoration(
color: VertexColors.white,
borderRadius: BorderRadius.all(
Radius.circular(100),
return AnimatedBuilder(
animation: _width,
builder: (context, child) {
return SizedBox(
width: _width.value,
child: RichText(
text: TextSpan(
children: [
for (final element in parsed.elements)
if (element.isLink)
WidgetSpan(
child: InkWell(
onTap: () {
final isOnSeeSourceAnswers =
context.read<HomeBloc>().state.status ==
Status.seeSourceAnswers;
if (isOnSeeSourceAnswers) {
context.read<HomeBloc>().add(
NavigateSourceAnswers(
element.text,
),
);
} else {
context.read<HomeBloc>().add(
SeeSourceAnswersRequested(
element.text,
),
);
}
},
child: Container(
margin: const EdgeInsets.symmetric(
horizontal: 2,
),
padding: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 12,
),
decoration: const BoxDecoration(
color: VertexColors.white,
borderRadius: BorderRadius.all(
Radius.circular(100),
),
),
child: Text(
element.text,
style: textTheme.labelLarge?.copyWith(
color: VertexColors.googleBlue,
),
),
),
),
child: Text(
element.text,
style: textTheme.labelLarge?.copyWith(
color: VertexColors.googleBlue,
),
)
else
TextSpan(
text: element.text,
style: textTheme.headlineLarge?.copyWith(
color: VertexColors.white,
),
),
),
)
else
TextSpan(
text: element.text,
style: textTheme.headlineLarge?.copyWith(
color: VertexColors.white,
),
),
],
),
),
],
),
),
);
},
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class _QuestionTextFieldState extends State<QuestionInputTextField> {
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Container(
constraints: const BoxConstraints(maxWidth: 600),
constraints: const BoxConstraints(maxWidth: 659),
child: TextField(
controller: _controller,
style: textTheme.bodyMedium?.copyWith(
Expand Down
38 changes: 23 additions & 15 deletions test/home/widgets/results_view_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:api_client/api_client.dart';
import 'package:app_ui/app_ui.dart';
import 'package:bloc_test/bloc_test.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:flutter_test/flutter_test.dart';
Expand Down Expand Up @@ -150,15 +151,6 @@ void main() {
expect(sizeIn, isNot(equals(originalSizeIn)));
});

testWidgets(
'calls Results on enter',
(WidgetTester tester) async {
await tester.pumpApp(bootstrap());
await tester.pumpAndSettle();
verify(() => homeBloc.add(Results())).called(1);
},
);

testWidgets(
'calls SeeResultsSourceAnswers on exit',
(WidgetTester tester) async {
Expand Down Expand Up @@ -201,8 +193,18 @@ void main() {
(tester) async {
await tester.pumpApp(bootstrap());

await tester.pumpAndSettle();
await tester.tap(find.byType(SeeSourceAnswersButton));
final l10n = tester.element(find.byType(ResultsView)).l10n;

await tester.pump();
tester
.widget<TertiaryCTA>(
find.ancestor(
of: find.text(l10n.seeSourceAnswers),
matching: find.byType(TertiaryCTA),
),
)
.onPressed
?.call();

verify(() => homeBloc.add(const SeeSourceAnswersRequested(null)))
.called(1);
Expand All @@ -211,8 +213,11 @@ void main() {
testWidgets('adds AnswerFeedback.good on thumbs up', (tester) async {
await tester.pumpApp(bootstrap());

await tester.pumpAndSettle();
await tester.tap(find.byType(CircleAvatar).first);
await tester.pump();
tester
.widget<FeedbackButtons>(find.byType(FeedbackButtons))
.onLike
?.call();

verify(
() => homeBloc.add(
Expand All @@ -224,8 +229,11 @@ void main() {
testWidgets('adds AnswerFeedback.bad on thumbs down', (tester) async {
await tester.pumpApp(bootstrap());

await tester.pumpAndSettle();
await tester.tap(find.byType(CircleAvatar).last);
await tester.pump();
tester
.widget<FeedbackButtons>(find.byType(FeedbackButtons))
.onDislike
?.call();

verify(
() => homeBloc.add(
Expand Down