feat: make all translations required for TimelineTranslations and provide an .empty() alternative

This commit is contained in:
Freek van de Ven 2024-05-22 11:43:55 +02:00
parent ad5390fff8
commit ab0f96121e
11 changed files with 110 additions and 66 deletions

View file

@ -10,6 +10,7 @@
- Add a refresh functionality to the timeline with a pull to refresh callback to allow additional functionality when refreshing the timeline - Add a refresh functionality to the timeline with a pull to refresh callback to allow additional functionality when refreshing the timeline
- Use the adaptive variants of the material elements in the timeline - Use the adaptive variants of the material elements in the timeline
- Change the default blue color to the primary color of the Theme.of(context) in the timeline - Change the default blue color to the primary color of the Theme.of(context) in the timeline
- Change the TimelineTranslations constructor to require all translations or use the TimelineTranslations.empty constructor if you don't want to specify all translations
## 3.0.1 ## 3.0.1

View file

@ -74,7 +74,7 @@ List<GoRoute> getTimelineStoryRoutes({
config config
.optionsBuilder(context) .optionsBuilder(context)
.translations .translations
.timeLineScreenTitle!, .timeLineScreenTitle,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
fontSize: 24, fontSize: 24,
@ -120,7 +120,7 @@ List<GoRoute> getTimelineStoryRoutes({
leading: backButton, leading: backButton,
backgroundColor: const Color(0xff212121), backgroundColor: const Color(0xff212121),
title: Text( title: Text(
config.optionsBuilder(context).translations.postCreation!, config.optionsBuilder(context).translations.postCreation,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
fontSize: 24, fontSize: 24,
@ -236,7 +236,7 @@ List<GoRoute> getTimelineStoryRoutes({
backgroundColor: const Color(0xff212121), backgroundColor: const Color(0xff212121),
leading: backButton, leading: backButton,
title: Text( title: Text(
config.optionsBuilder(context).translations.postCreation!, config.optionsBuilder(context).translations.postCreation,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
fontSize: 24, fontSize: 24,
@ -284,7 +284,7 @@ List<GoRoute> getTimelineStoryRoutes({
leading: backButton, leading: backButton,
backgroundColor: const Color(0xff212121), backgroundColor: const Color(0xff212121),
title: Text( title: Text(
config.optionsBuilder(context).translations.postOverview!, config.optionsBuilder(context).translations.postOverview,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
fontSize: 24, fontSize: 24,

View file

@ -92,7 +92,7 @@ Widget _timelineScreenRoute({
appBar: AppBar( appBar: AppBar(
backgroundColor: const Color(0xff212121), backgroundColor: const Color(0xff212121),
title: Text( title: Text(
config.optionsBuilder(context).translations.timeLineScreenTitle!, config.optionsBuilder(context).translations.timeLineScreenTitle,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
fontSize: 24, fontSize: 24,
@ -246,7 +246,7 @@ Widget _postCreationScreenRoute({
backgroundColor: const Color(0xff212121), backgroundColor: const Color(0xff212121),
leading: backButton, leading: backButton,
title: Text( title: Text(
config.optionsBuilder(context).translations.postCreation!, config.optionsBuilder(context).translations.postCreation,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
fontSize: 24, fontSize: 24,
@ -313,7 +313,7 @@ Widget _postOverviewScreenRoute({
leading: backButton, leading: backButton,
backgroundColor: const Color(0xff212121), backgroundColor: const Color(0xff212121),
title: Text( title: Text(
config.optionsBuilder(context).translations.postOverview!, config.optionsBuilder(context).translations.postOverview,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
fontSize: 24, fontSize: 24,
@ -372,7 +372,7 @@ Widget _postCategorySelectionScreen({
leading: backButton, leading: backButton,
backgroundColor: const Color(0xff212121), backgroundColor: const Color(0xff212121),
title: Text( title: Text(
config.optionsBuilder(context).translations.postCreation!, config.optionsBuilder(context).translations.postCreation,
style: TextStyle( style: TextStyle(
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
fontSize: 24, fontSize: 24,

View file

@ -12,7 +12,7 @@ import 'package:intl/intl.dart';
class TimelineOptions { class TimelineOptions {
const TimelineOptions({ const TimelineOptions({
this.theme = const TimelineTheme(), this.theme = const TimelineTheme(),
this.translations = const TimelineTranslations(), this.translations = const TimelineTranslations.empty(),
this.imagePickerConfig = const ImagePickerConfig(), this.imagePickerConfig = const ImagePickerConfig(),
this.imagePickerTheme = const ImagePickerTheme(), this.imagePickerTheme = const ImagePickerTheme(),
this.timelinePostHeight, this.timelinePostHeight,

View file

@ -5,8 +5,50 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@immutable @immutable
/// Class that holds all the translations for the timeline component view and
/// the corresponding userstory
class TimelineTranslations { class TimelineTranslations {
/// TimelineTranslations constructor where everything is required use this
/// if you want to be sure to have all translations specified
/// If you just want the default values use the empty constructor
/// and optionally override the values with the copyWith method
const TimelineTranslations({ const TimelineTranslations({
required this.anonymousUser,
required this.noPosts,
required this.noPostsWithFilter,
required this.title,
required this.titleHintText,
required this.content,
required this.contentHintText,
required this.contentDescription,
required this.uploadImage,
required this.uploadImageDescription,
required this.allowComments,
required this.allowCommentsDescription,
required this.commentsTitleOnPost,
required this.checkPost,
required this.postAt,
required this.deletePost,
required this.deleteReaction,
required this.viewPost,
required this.likesTitle,
required this.commentsTitle,
required this.firstComment,
required this.writeComment,
required this.postLoadingError,
required this.timelineSelectionDescription,
required this.searchHint,
required this.postOverview,
required this.postIn,
required this.postCreation,
required this.yes,
required this.no,
required this.timeLineScreenTitle,
});
/// Default translations for the timeline component view
const TimelineTranslations.empty({
this.anonymousUser = 'Anonymous user', this.anonymousUser = 'Anonymous user',
this.noPosts = 'No posts yet', this.noPosts = 'No posts yet',
this.noPostsWithFilter = 'No posts with this filter', this.noPostsWithFilter = 'No posts with this filter',
@ -41,45 +83,46 @@ class TimelineTranslations {
this.timeLineScreenTitle = 'iconinstagram', this.timeLineScreenTitle = 'iconinstagram',
}); });
final String? noPosts; final String noPosts;
final String? noPostsWithFilter; final String noPostsWithFilter;
final String? anonymousUser; final String anonymousUser;
final String? title; final String title;
final String? content; final String content;
final String? contentDescription; final String contentDescription;
final String? uploadImage; final String uploadImage;
final String? uploadImageDescription; final String uploadImageDescription;
final String? allowComments; final String allowComments;
final String? allowCommentsDescription; final String allowCommentsDescription;
final String? checkPost; final String checkPost;
final String? postAt; final String postAt;
final String? titleHintText; final String titleHintText;
final String? contentHintText; final String contentHintText;
final String? deletePost; final String deletePost;
final String? deleteReaction; final String deleteReaction;
final String? viewPost; final String viewPost;
final String? likesTitle; final String likesTitle;
final String? commentsTitle; final String commentsTitle;
final String? commentsTitleOnPost; final String commentsTitleOnPost;
final String? writeComment; final String writeComment;
final String? firstComment; final String firstComment;
final String? postLoadingError; final String postLoadingError;
final String? timelineSelectionDescription; final String timelineSelectionDescription;
final String? searchHint; final String searchHint;
final String? postOverview; final String postOverview;
final String? postIn; final String postIn;
final String? postCreation; final String postCreation;
final String? yes; final String yes;
final String? no; final String no;
final String? timeLineScreenTitle; final String timeLineScreenTitle;
/// Method to override the default values of the translations
TimelineTranslations copyWith({ TimelineTranslations copyWith({
String? noPosts, String? noPosts,
String? noPostsWithFilter, String? noPostsWithFilter,

View file

@ -128,7 +128,7 @@ class _TimelinePostCreationScreenState
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
widget.options.translations.title!, widget.options.translations.title,
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
fontSize: 20, fontSize: 20,
@ -149,7 +149,7 @@ class _TimelinePostCreationScreenState
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
widget.options.translations.content!, widget.options.translations.content,
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
fontSize: 20, fontSize: 20,
@ -157,7 +157,7 @@ class _TimelinePostCreationScreenState
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
widget.options.translations.contentDescription!, widget.options.translations.contentDescription,
style: theme.textTheme.bodyMedium, style: theme.textTheme.bodyMedium,
), ),
// input field for the content // input field for the content
@ -177,14 +177,14 @@ class _TimelinePostCreationScreenState
), ),
// input field for the content // input field for the content
Text( Text(
widget.options.translations.uploadImage!, widget.options.translations.uploadImage,
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
fontSize: 20, fontSize: 20,
), ),
), ),
Text( Text(
widget.options.translations.uploadImageDescription!, widget.options.translations.uploadImageDescription,
style: theme.textTheme.bodyMedium, style: theme.textTheme.bodyMedium,
), ),
// image picker field // image picker field
@ -271,14 +271,14 @@ class _TimelinePostCreationScreenState
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
widget.options.translations.commentsTitle!, widget.options.translations.commentsTitle,
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
fontSize: 20, fontSize: 20,
), ),
), ),
Text( Text(
widget.options.translations.allowCommentsDescription!, widget.options.translations.allowCommentsDescription,
style: theme.textTheme.bodyMedium, style: theme.textTheme.bodyMedium,
), ),
Row( Row(
@ -293,7 +293,7 @@ class _TimelinePostCreationScreenState
}); });
}, },
), ),
Text(widget.options.translations.yes!), Text(widget.options.translations.yes),
Checkbox( Checkbox(
activeColor: theme.colorScheme.primary, activeColor: theme.colorScheme.primary,
value: !allowComments, value: !allowComments,
@ -303,7 +303,7 @@ class _TimelinePostCreationScreenState
}); });
}, },
), ),
Text(widget.options.translations.no!), Text(widget.options.translations.no),
], ],
), ),
const SizedBox(height: 120), const SizedBox(height: 120),
@ -314,7 +314,7 @@ class _TimelinePostCreationScreenState
? widget.options.buttonBuilder!( ? widget.options.buttonBuilder!(
context, context,
onPostCreated, onPostCreated,
widget.options.translations.checkPost!, widget.options.translations.checkPost,
enabled: editingDone, enabled: editingDone,
) )
: ElevatedButton( : ElevatedButton(
@ -334,8 +334,8 @@ class _TimelinePostCreationScreenState
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12.0),
child: Text( child: Text(
widget.enablePostOverviewScreen widget.enablePostOverviewScreen
? widget.options.translations.checkPost! ? widget.options.translations.checkPost
: widget.options.translations.postCreation!, : widget.options.translations.postCreation,
style: const TextStyle( style: const TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 20, fontSize: 20,

View file

@ -150,7 +150,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
if (this.post == null) { if (this.post == null) {
return Center( return Center(
child: Text( child: Text(
widget.options.translations.postLoadingError!, widget.options.translations.postLoadingError,
style: widget.options.theme.textStyles.errorTextStyle, style: widget.options.theme.textStyles.errorTextStyle,
), ),
); );
@ -219,7 +219,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
widget.options.nameBuilder widget.options.nameBuilder
?.call(post.creator) ?? ?.call(post.creator) ??
post.creator?.fullName ?? post.creator?.fullName ??
widget.options.translations.anonymousUser!, widget.options.translations.anonymousUser,
style: widget.options.theme.textStyles style: widget.options.theme.textStyles
.postCreatorTitleStyle ?? .postCreatorTitleStyle ??
theme.textTheme.titleMedium, theme.textTheme.titleMedium,
@ -239,7 +239,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
child: Row( child: Row(
children: [ children: [
Text( Text(
widget.options.translations.deletePost!, widget.options.translations.deletePost,
style: widget.options.theme.textStyles style: widget.options.theme.textStyles
.deletePostStyle ?? .deletePostStyle ??
theme.textTheme.bodyMedium, theme.textTheme.bodyMedium,
@ -439,7 +439,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
const SizedBox(height: 20), const SizedBox(height: 20),
if (post.reactionEnabled) ...[ if (post.reactionEnabled) ...[
Text( Text(
widget.options.translations.commentsTitleOnPost!, widget.options.translations.commentsTitleOnPost,
style: theme.textTheme.titleMedium, style: theme.textTheme.titleMedium,
), ),
for (var reaction for (var reaction
@ -467,7 +467,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
PopupMenuItem<String>( PopupMenuItem<String>(
value: 'delete', value: 'delete',
child: Text( child: Text(
widget.options.translations.deleteReaction!, widget.options.translations.deleteReaction,
), ),
), ),
], ],
@ -521,7 +521,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
?.call(post.creator) ?? ?.call(post.creator) ??
reaction.creator?.fullName ?? reaction.creator?.fullName ??
widget.options.translations widget.options.translations
.anonymousUser!, .anonymousUser,
style: theme.textTheme.titleSmall, style: theme.textTheme.titleSmall,
), ),
Padding( Padding(
@ -563,7 +563,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
if (post.reactions?.isEmpty ?? true) ...[ if (post.reactions?.isEmpty ?? true) ...[
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
widget.options.translations.firstComment!, widget.options.translations.firstComment,
), ),
], ],
const SizedBox(height: 120), const SizedBox(height: 120),

View file

@ -289,9 +289,9 @@ class _TimelineScreenState extends State<TimelineScreen> {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text( child: Text(
category == null category == null
? widget.options.translations.noPosts! ? widget.options.translations.noPosts
: widget : widget
.options.translations.noPostsWithFilter!, .options.translations.noPostsWithFilter,
style: style:
widget.options.theme.textStyles.noPostsStyle, widget.options.theme.textStyles.noPostsStyle,
), ),

View file

@ -29,7 +29,7 @@ class TimelineSelectionScreen extends StatelessWidget {
Padding( Padding(
padding: EdgeInsets.only(top: size.height * 0.05, bottom: 8), padding: EdgeInsets.only(top: size.height * 0.05, bottom: 8),
child: Text( child: Text(
options.translations.timelineSelectionDescription!, options.translations.timelineSelectionDescription,
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
fontSize: 20, fontSize: 20,

View file

@ -65,7 +65,7 @@ class _ReactionBottomState extends State<ReactionBottom> {
], ],
), ),
), ),
widget.translations.writeComment!, widget.translations.writeComment,
), ),
), ),
), ),

View file

@ -94,7 +94,7 @@ class _TimelinePostWidgetState extends State<TimelinePostWidget> {
widget.options.nameBuilder widget.options.nameBuilder
?.call(widget.post.creator) ?? ?.call(widget.post.creator) ??
widget.post.creator?.fullName ?? widget.post.creator?.fullName ??
widget.options.translations.anonymousUser!, widget.options.translations.anonymousUser,
style: widget.options.theme.textStyles style: widget.options.theme.textStyles
.postCreatorTitleStyle ?? .postCreatorTitleStyle ??
theme.textTheme.titleMedium, theme.textTheme.titleMedium,
@ -118,7 +118,7 @@ class _TimelinePostWidgetState extends State<TimelinePostWidget> {
child: Row( child: Row(
children: [ children: [
Text( Text(
widget.options.translations.deletePost!, widget.options.translations.deletePost,
style: widget.options.theme.textStyles style: widget.options.theme.textStyles
.deletePostStyle ?? .deletePostStyle ??
theme.textTheme.bodyMedium, theme.textTheme.bodyMedium,
@ -318,7 +318,7 @@ class _TimelinePostWidgetState extends State<TimelinePostWidget> {
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
widget.options.translations.viewPost!, widget.options.translations.viewPost,
style: widget.options.theme.textStyles.viewPostStyle ?? style: widget.options.theme.textStyles.viewPostStyle ??
theme.textTheme.bodySmall, theme.textTheme.bodySmall,
), ),