Skip to content

Commit ac4f1da

Browse files
committed
ui enhancements #22
1 parent 8ca69a4 commit ac4f1da

File tree

19 files changed

+175
-86
lines changed

19 files changed

+175
-86
lines changed

assets/fonts/Poppins-Regular.ttf

155 KB
Binary file not shown.
File renamed without changes.
File renamed without changes.

lib/app/l10n/arb/app_de.arb

+2-2
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,9 @@
166166
}
167167
}
168168
},
169-
"analyzeText": "Text Analysieren",
169+
"analyzeText": "Analysieren",
170170
"@analyzeText": {
171-
"description": "Analyze Text button text on the OnboardingView",
171+
"description": "Analyze button text on the OnboardingView",
172172
"type": "text",
173173
"placeholders": {}
174174
}

lib/app/l10n/arb/app_en.arb

+2-2
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,9 @@
166166
}
167167
}
168168
},
169-
"analyzeText": "Analyze Text",
169+
"analyzeText": "Analyze",
170170
"@analyzeText": {
171-
"description": "Analyze Text button text on the OnboardingView",
171+
"description": "Analyze button text on the OnboardingView",
172172
"type": "text",
173173
"placeholders": {}
174174
}

lib/app/theme/base/base_theme.dart

+38-43
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import 'package:flutter/material.dart';
22
import 'package:gpt_detector/app/theme/theme_constants.dart';
3-
import 'package:gpt_detector/app/theme/theme_extensions/theme_extensions.dart';
43

54
abstract base class BaseTheme {
65
Brightness get brightness;
7-
Iterable<ThemeExtension<ThemeExtensions>> get extensions;
6+
Iterable<ThemeExtension<ThemeExtension>> get extensions;
87

98
ThemeData get theme {
109
return ThemeData(
11-
useMaterial3: true,
10+
fontFamily: 'Poppins',
1211
brightness: brightness,
1312
extensions: extensions,
1413
colorSchemeSeed: Colors.deepPurple,
@@ -22,51 +21,47 @@ abstract base class BaseTheme {
2221
);
2322
}
2423

25-
AppBarTheme get _appBarTheme {
26-
return const AppBarTheme(
27-
centerTitle: true,
28-
);
29-
}
30-
31-
CardTheme get _cardTheme {
32-
return CardTheme(
33-
margin: EdgeInsets.zero,
34-
elevation: ThemeConstants.elevation,
35-
shape: RoundedRectangleBorder(
36-
borderRadius: ThemeConstants.borderRadiusCircular,
37-
),
38-
);
39-
}
24+
final AppBarTheme _appBarTheme = const AppBarTheme(
25+
centerTitle: true,
26+
);
4027

41-
DialogTheme get _dialogTheme {
42-
return DialogTheme(
43-
elevation: ThemeConstants.elevation,
44-
shape: RoundedRectangleBorder(
45-
borderRadius: ThemeConstants.borderRadiusCircular,
46-
),
47-
);
48-
}
28+
final CardTheme _cardTheme = CardTheme(
29+
margin: EdgeInsets.zero,
30+
elevation: ThemeConstants.elevation,
31+
shape: RoundedRectangleBorder(
32+
borderRadius: ThemeConstants.borderRadiusCircular,
33+
),
34+
);
4935

50-
final ExpansionTileThemeData _expansionTileThemeData =
51-
const ExpansionTileThemeData(tilePadding: EdgeInsets.zero, shape: Border());
36+
final DialogTheme _dialogTheme = DialogTheme(
37+
elevation: ThemeConstants.elevation,
38+
shape: RoundedRectangleBorder(
39+
borderRadius: ThemeConstants.borderRadiusCircular,
40+
),
41+
);
5242

53-
final ListTileThemeData _listTileThemeData = const ListTileThemeData(contentPadding: EdgeInsets.zero);
43+
final ExpansionTileThemeData _expansionTileThemeData = const ExpansionTileThemeData(
44+
tilePadding: EdgeInsets.zero,
45+
shape: Border(),
46+
);
5447

55-
ElevatedButtonThemeData get _elevatedButtonTheme => ElevatedButtonThemeData(
56-
style: ElevatedButton.styleFrom(
57-
elevation: ThemeConstants.elevation,
58-
minimumSize: const Size.fromHeight(kToolbarHeight),
59-
shape: RoundedRectangleBorder(
60-
borderRadius: ThemeConstants.borderRadiusCircular,
61-
),
62-
),
63-
);
48+
final ListTileThemeData _listTileThemeData = const ListTileThemeData(
49+
contentPadding: EdgeInsets.zero,
50+
);
6451

65-
InputDecorationTheme get _inputDecorationTheme {
66-
return InputDecorationTheme(
67-
border: OutlineInputBorder(
52+
final ElevatedButtonThemeData _elevatedButtonTheme = ElevatedButtonThemeData(
53+
style: ElevatedButton.styleFrom(
54+
elevation: ThemeConstants.elevation,
55+
minimumSize: const Size.fromHeight(kToolbarHeight),
56+
shape: RoundedRectangleBorder(
6857
borderRadius: ThemeConstants.borderRadiusCircular,
6958
),
70-
);
71-
}
59+
),
60+
);
61+
62+
final InputDecorationTheme _inputDecorationTheme = InputDecorationTheme(
63+
border: OutlineInputBorder(
64+
borderRadius: ThemeConstants.borderRadiusCircular,
65+
),
66+
);
7267
}

lib/app/theme/dark/dark_theme.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ final class DarkTheme extends BaseTheme {
99
Brightness get brightness => Brightness.dark;
1010

1111
@override
12-
Iterable<ThemeExtension<ThemeExtensions>> get extensions => [
13-
ThemeExtensions(
12+
Iterable<ThemeExtension<AppThemeExtensions>> get extensions => [
13+
AppThemeExtensions(
1414
humanContent: const Color(0xFF479985),
1515
aiContent: const Color(0xFF93000A),
1616
mixedContent: const Color(0xFFFF7E79),

lib/app/theme/light/light_theme.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ final class LightTheme extends BaseTheme {
99
Brightness get brightness => Brightness.light;
1010

1111
@override
12-
Iterable<ThemeExtension<ThemeExtensions>> get extensions => [
13-
ThemeExtensions(
12+
Iterable<ThemeExtension<AppThemeExtensions>> get extensions => [
13+
AppThemeExtensions(
1414
humanContent: const Color(0xFF007256),
1515
aiContent: const Color(0xFFBA1A1A),
1616
mixedContent: const Color(0xFFFF7E79),

lib/app/theme/theme_constants.dart

+4
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ abstract final class ThemeConstants {
44
static final BorderRadius borderRadiusCircular = BorderRadius.circular(12);
55
static const Radius radiusCircular = Radius.circular(12);
66
static const double elevation = 2;
7+
8+
static const FontWeight fontWeightRegular = FontWeight.w400;
9+
static const FontWeight fontWeightSemiBold = FontWeight.w500;
10+
static const FontWeight fontWeightBold = FontWeight.w600;
711
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'package:flutter/material.dart';
22

3-
class ThemeExtensions extends ThemeExtension<ThemeExtensions> {
4-
ThemeExtensions({
3+
class AppThemeExtensions extends ThemeExtension<AppThemeExtensions> {
4+
AppThemeExtensions({
55
required this.humanContent,
66
required this.mixedContent,
77
required this.aiContent,
@@ -12,24 +12,24 @@ class ThemeExtensions extends ThemeExtension<ThemeExtensions> {
1212
final Color? aiContent;
1313

1414
@override
15-
ThemeExtension<ThemeExtensions> lerp(ThemeExtension<ThemeExtensions>? other, double t) {
16-
if (other is! ThemeExtensions) {
15+
ThemeExtension<AppThemeExtensions> lerp(ThemeExtension<AppThemeExtensions>? other, double t) {
16+
if (other is! AppThemeExtensions) {
1717
return this;
1818
}
19-
return ThemeExtensions(
19+
return AppThemeExtensions(
2020
humanContent: Color.lerp(humanContent, other.humanContent, t),
2121
mixedContent: Color.lerp(mixedContent, other.mixedContent, t),
2222
aiContent: Color.lerp(aiContent, other.aiContent, t),
2323
);
2424
}
2525

2626
@override
27-
ThemeExtensions copyWith({
27+
AppThemeExtensions copyWith({
2828
Color? humanContent,
2929
Color? mixedContent,
3030
Color? aiContent,
3131
}) {
32-
return ThemeExtensions(
32+
return AppThemeExtensions(
3333
humanContent: humanContent ?? this.humanContent,
3434
mixedContent: mixedContent ?? this.mixedContent,
3535
aiContent: aiContent ?? this.aiContent,
@@ -38,5 +38,5 @@ class ThemeExtensions extends ThemeExtension<ThemeExtensions> {
3838

3939
@override
4040
String toString() =>
41-
'ThemeExtensions(humanContent: $humanContent, mixedContent: $mixedContent, aiContent: $aiContent)';
41+
'AppThemeExtensions(humanContent: $humanContent, mixedContent: $mixedContent, aiContent: $aiContent)';
4242
}
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:gpt_detector/app/theme/theme_constants.dart';
3+
import 'package:gpt_detector/core/extensions/context_extensions.dart';
4+
5+
class GPTElevatedButton extends StatelessWidget {
6+
const GPTElevatedButton({required this.text, required this.onPressed, super.key, this.showingLoadingIndicator});
7+
8+
final bool? showingLoadingIndicator;
9+
final void Function()? onPressed;
10+
final String text;
11+
12+
@override
13+
Widget build(BuildContext context) {
14+
return ElevatedButton(
15+
style: ElevatedButton.styleFrom(
16+
backgroundColor: context.colorScheme.primary,
17+
foregroundColor: context.colorScheme.onPrimary,
18+
),
19+
onPressed: showingLoadingIndicator ?? false ? null : onPressed,
20+
child: showingLoadingIndicator ?? false
21+
? const CircularProgressIndicator.adaptive()
22+
: Text(
23+
text,
24+
style: context.textTheme.bodyLarge?.copyWith(
25+
color: context.colorScheme.onPrimary,
26+
fontWeight: ThemeConstants.fontWeightBold,
27+
),
28+
),
29+
);
30+
}
31+
}

lib/core/extensions/context_extensions.dart

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'package:flutter/material.dart';
22

3-
extension MediaQueryExtension on BuildContext {
3+
extension MediaQueryExtensions on BuildContext {
44
MediaQueryData get mediaQuery => MediaQuery.of(this);
55

66
/// Returns the height of the device
@@ -40,7 +40,7 @@ extension MediaQueryExtension on BuildContext {
4040
double dynamicHeight(double val) => height * val;
4141
}
4242

43-
extension PaddingExtension on BuildContext {
43+
extension PaddingExtensions on BuildContext {
4444
/// Adds 1% padding from all sides.
4545
EdgeInsets get paddingAllLow => EdgeInsets.all(lowValue);
4646

@@ -112,7 +112,7 @@ extension PaddingExtension on BuildContext {
112112
EdgeInsets get paddingBottomHigh => EdgeInsets.only(bottom: highValue);
113113
}
114114

115-
extension ThemeExtension on BuildContext {
115+
extension ThemeExtensions on BuildContext {
116116
/// Get the theme data
117117
ThemeData get theme => Theme.of(this);
118118

@@ -121,4 +121,7 @@ extension ThemeExtension on BuildContext {
121121

122122
/// Get the brightness
123123
Brightness get brightness => Theme.of(this).brightness;
124+
125+
/// Get the color scheme
126+
ColorScheme get colorScheme => Theme.of(this).colorScheme;
124127
}
+16-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
11
import 'package:flutter/material.dart';
22
import 'package:gpt_detector/app/constants/duration_constants.dart';
3+
import 'package:gpt_detector/app/theme/theme_constants.dart';
4+
import 'package:gpt_detector/core/extensions/context_extensions.dart';
35

46
abstract final class SnackbarUtils {
57
static void showSnackbar({required BuildContext context, required String message}) {
68
ScaffoldMessenger.of(context)
79
..hideCurrentSnackBar()
8-
..showSnackBar(SnackBar(content: Text(message), duration: DurationConstants.s4()));
10+
..showSnackBar(
11+
SnackBar(
12+
padding: EdgeInsets.all(context.defaultValue),
13+
content: Text(
14+
message,
15+
style: context.textTheme.bodyLarge?.copyWith(
16+
color: context.theme.colorScheme.onPrimary,
17+
fontWeight: ThemeConstants.fontWeightSemiBold,
18+
),
19+
),
20+
duration: DurationConstants.s4(),
21+
behavior: SnackBarBehavior.fixed,
22+
),
23+
);
924
}
1025
}

lib/feature/detector/data/model/detector/detector_model.dart

+4-4
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ enum Classification {
6060
switch (this) {
6161
// Return default card color in case initial
6262
case Classification.initial:
63-
return themeData.cardColor;
63+
return themeData.secondaryHeaderColor;
6464
case Classification.human:
65-
return themeData.extension<ThemeExtensions>()?.humanContent ?? themeData.cardColor;
65+
return themeData.extension<AppThemeExtensions>()?.humanContent ?? themeData.secondaryHeaderColor;
6666
case Classification.ai:
67-
return themeData.extension<ThemeExtensions>()?.aiContent ?? themeData.cardColor;
67+
return themeData.extension<AppThemeExtensions>()?.aiContent ?? themeData.secondaryHeaderColor;
6868
case Classification.mixed:
69-
return themeData.extension<ThemeExtensions>()?.mixedContent ?? themeData.cardColor;
69+
return themeData.extension<AppThemeExtensions>()?.mixedContent ?? themeData.secondaryHeaderColor;
7070
}
7171
}
7272
}

lib/feature/detector/presentation/cubit/detector_cubit.dart

+17-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
import 'package:flutter/material.dart';
12
import 'package:flutter_bloc/flutter_bloc.dart';
23
import 'package:form_inputs/form_inputs.dart';
34
import 'package:freezed_annotation/freezed_annotation.dart';
45

56
import 'package:gpt_detector/app/errors/failure.dart';
7+
import 'package:gpt_detector/app/l10n/extensions/app_l10n_extensions.dart';
8+
import 'package:gpt_detector/core/utils/snackbar/snackbar_utils.dart';
69
import 'package:gpt_detector/feature/detector/domain/entities/detector/detector_entity.dart';
710
import 'package:gpt_detector/feature/detector/domain/use_cases/detect_use_case.dart';
811
import 'package:gpt_detector/feature/detector/domain/use_cases/has_camera_permission_use_case.dart';
@@ -45,9 +48,21 @@ class DetectorCubit extends Cubit<DetectorState> {
4548
emit(state.copyWith(hasGalleryPermission: hasGalleryPermission));
4649
}
4750

48-
Future<void> detectionRequested({required String text}) async {
51+
Future<void> detectionRequested({required BuildContext context, required String text}) async {
52+
// Validate user input
53+
final formStatus = UserInputForm.dirty(text);
54+
if (formStatus.invalid) {
55+
switch (formStatus.error) {
56+
case UserInputFormError.tooShort:
57+
SnackbarUtils.showSnackbar(context: context, message: context.l10n.textFieldHelperShortText);
58+
case UserInputFormError.tooLong:
59+
SnackbarUtils.showSnackbar(context: context, message: context.l10n.textFieldHelperLongText);
60+
case null:
61+
}
62+
return;
63+
}
64+
// Call use case
4965
emit(state.copyWith(status: FormzStatus.submissionInProgress));
50-
5166
final response = await _detectUseCase.call(text);
5267

5368
response.fold(

0 commit comments

Comments
 (0)