add time selection when sending

This commit is contained in:
otsmr 2025-02-04 00:22:18 +01:00
parent 5675437bc0
commit d3bc0dc135
16 changed files with 218 additions and 184 deletions

View file

@ -1,7 +1,7 @@
import 'dart:collection';
import 'package:fixnum/fixnum.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/components/flame.dart';
import 'package:twonly/src/components/headline.dart';
import 'package:twonly/src/components/initialsavatar.dart';
@ -29,7 +29,7 @@ class BestFriendsSelector extends StatelessWidget {
return Column(
children: [
HeadLineComponent(AppLocalizations.of(context)!.shareImageBestFriends),
HeadLineComponent(context.lang.shareImageBestFriends),
Column(
spacing: 8,
children: List.generate(

View file

@ -5,16 +5,27 @@ class ActionButton extends StatelessWidget {
final VoidCallback? onPressed;
final IconData? icon;
final Color? color;
final String tooltipText;
final bool disable;
const ActionButton(this.icon, {super.key, this.onPressed, this.color});
const ActionButton(this.icon,
{super.key,
this.onPressed,
this.color,
required this.tooltipText,
this.disable = false});
@override
Widget build(BuildContext context) {
return IconButton(
return Tooltip(
message: tooltipText,
child: IconButton(
icon: FaIcon(
icon,
size: 30,
color: color ?? Colors.white,
color: disable
? const Color.fromARGB(154, 255, 255, 255)
: color ?? Colors.white,
shadows: [
Shadow(
color: const Color.fromARGB(122, 0, 0, 0),
@ -22,7 +33,10 @@ class ActionButton extends StatelessWidget {
)
],
),
onPressed: onPressed,
onPressed: () {
if (!disable && onPressed != null) onPressed!();
},
),
);
}
}

View file

@ -4,6 +4,7 @@ import 'package:hand_signature/signature.dart';
import 'package:screenshot/screenshot.dart';
import 'package:twonly/src/components/image_editor/action_button.dart';
import 'package:twonly/src/components/image_editor/data/layer.dart';
import 'package:twonly/src/utils/misc.dart';
class DrawLayer extends StatefulWidget {
final DrawLayerData layerData;
@ -106,6 +107,7 @@ class _DrawLayerState extends State<DrawLayer> {
children: [
ActionButton(
FontAwesomeIcons.check,
tooltipText: context.lang.imageEditorDrawOk,
onPressed: () async {
widget.layerData.isEditing = false;
},
@ -113,6 +115,7 @@ class _DrawLayerState extends State<DrawLayer> {
Expanded(child: Container()),
ActionButton(
FontAwesomeIcons.arrowRotateLeft,
tooltipText: context.lang.undo,
color: widget.layerData.control.paths.isNotEmpty
? Colors.white
: Colors.white.withAlpha(80),
@ -125,6 +128,7 @@ class _DrawLayerState extends State<DrawLayer> {
},
),
ActionButton(
tooltipText: context.lang.redo,
FontAwesomeIcons.arrowRotateRight,
color: undoList.isNotEmpty
? Colors.white

View file

@ -150,6 +150,7 @@ class _TextViewState extends State<TextLayer> {
},
child: ActionButton(
FontAwesomeIcons.trashCan,
tooltipText: "",
color: deleteLayer ? Colors.red : Colors.white,
),
),

View file

@ -4,7 +4,7 @@ import 'package:provider/provider.dart';
import 'package:twonly/src/model/json/message.dart';
import 'package:twonly/src/model/messages_model.dart';
import 'package:twonly/src/providers/download_change_provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:twonly/src/utils/misc.dart';
enum MessageSendState {
received,
@ -44,29 +44,29 @@ class MessageSendStateIcon extends StatelessWidget {
switch (message.getSendState()) {
case MessageSendState.receivedOpened:
icon = Icon(Icons.crop_square, size: 14, color: color);
text = AppLocalizations.of(context)!.messageSendState_Received;
text = context.lang.messageSendState_Received;
break;
case MessageSendState.sendOpened:
icon = FaIcon(FontAwesomeIcons.paperPlane, size: 12, color: color);
text = AppLocalizations.of(context)!.messageSendState_Opened;
text = context.lang.messageSendState_Opened;
break;
case MessageSendState.received:
icon = Icon(Icons.square_rounded, size: 14, color: color);
text = AppLocalizations.of(context)!.messageSendState_Received;
text = context.lang.messageSendState_Received;
break;
case MessageSendState.send:
icon = FaIcon(FontAwesomeIcons.solidPaperPlane, size: 12, color: color);
text = AppLocalizations.of(context)!.messageSendState_Send;
text = context.lang.messageSendState_Send;
break;
case MessageSendState.sending:
case MessageSendState.receiving:
icon = loaderIcon;
text = AppLocalizations.of(context)!.messageSendState_Sending;
text = context.lang.messageSendState_Sending;
break;
}
if (!message.isDownloaded) {
text = AppLocalizations.of(context)!.messageSendState_TapToLoad;
text = context.lang.messageSendState_TapToLoad;
}
bool isDownloading = false;
@ -78,7 +78,7 @@ class MessageSendStateIcon extends StatelessWidget {
}
if (isDownloading) {
text = AppLocalizations.of(context)!.messageSendState_Loading;
text = context.lang.messageSendState_Loading;
icon = loaderIcon;
}

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
class NotificationBadge extends StatelessWidget {
final int count;
final String count;
final Widget child;
const NotificationBadge(
@ -9,22 +9,24 @@ class NotificationBadge extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (count == 0) return child;
if (count == "0") return child;
bool infinity = count == "";
return Stack(
children: [
child,
Positioned(
right: 5,
right: 3,
top: 0,
child: Container(
padding: EdgeInsets.all(5.0), // Add some padding
decoration: BoxDecoration(
color: Colors.red, // Background color
shape: BoxShape.circle, // Make it circular
),
child: SizedBox(
height: 18,
width: 18,
child: CircleAvatar(
backgroundColor: Colors.red,
child: Center(
child: Transform.rotate(
angle: infinity ? 90 * (3.141592653589793 / 180) : 0,
child: Text(
count.toString(),
infinity ? "8" : count,
style: TextStyle(
color: Colors.white, // Text color
fontSize: 10,
@ -32,6 +34,8 @@ class NotificationBadge extends StatelessWidget {
),
),
),
),
),
)
],
);

View file

@ -29,6 +29,16 @@
"messageSendState_Sending": "Sending",
"messageSendState_TapToLoad": "Tap to load",
"messageSendState_Loading": "Downloading",
"imageEditorDrawOk": "Take drawing",
"undo": "Undo",
"redo": "Redo",
"close": "Close",
"switchFrontAndBackCamera": "Switch between front and back camera.",
"addTextItem": "Text",
"protectAsARealTwonly": "Send as real twonly!",
"addDrawing": "Drawing",
"addEmoji": "Emoji",
"toogleFlashLight": "Toggle the flash light",
"chatListDetailTitle": "Your chat with {username}",
"searchUsernameNotFoundLong": "\"{username}\" is not a twonly user. Please check the username and try again.",
"errorUnknown": "An unexpected error has occurred. Please try again later.",

View file

@ -154,7 +154,8 @@ Future encryptAndUploadMediaFile(Int64 target, Uint8List imageBytes) async {
await uploadMediaFile(messageId, target, encryptBytes);
}
Future sendImage(List<Int64> userIds, Uint8List imageBytes) async {
Future sendImage(List<Int64> userIds, Uint8List imageBytes, bool isRealTwonly,
int maxShowTime) async {
// 1. set notifier provider
Uint8List? imageBytesCompressed = await getCompressedImage(imageBytes);

View file

@ -10,6 +10,10 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:twonly/src/proto/api/error.pb.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
extension LocalizationExtension on BuildContext {
AppLocalizations get lang => AppLocalizations.of(this)!;
}
Future<void> writeLogToFile(LogRecord record) async {
final directory = await getApplicationDocumentsDirectory();
final logFile = File('${directory.path}/app.log');
@ -57,31 +61,31 @@ Uint8List getRandomUint8List(int length) {
String errorCodeToText(BuildContext context, ErrorCode code) {
switch (code.toString()) {
case "Unknown":
return AppLocalizations.of(context)!.errorUnknown;
return context.lang.errorUnknown;
case "BadRequest":
return AppLocalizations.of(context)!.errorBadRequest;
return context.lang.errorBadRequest;
case "TooManyRequests":
return AppLocalizations.of(context)!.errorTooManyRequests;
return context.lang.errorTooManyRequests;
case "InternalError":
return AppLocalizations.of(context)!.errorInternalError;
return context.lang.errorInternalError;
case "InvalidInvitationCode":
return AppLocalizations.of(context)!.errorInvalidInvitationCode;
return context.lang.errorInvalidInvitationCode;
case "UsernameAlreadyTaken":
return AppLocalizations.of(context)!.errorUsernameAlreadyTaken;
return context.lang.errorUsernameAlreadyTaken;
case "SignatureNotValid":
return AppLocalizations.of(context)!.errorSignatureNotValid;
return context.lang.errorSignatureNotValid;
case "UsernameNotFound":
return AppLocalizations.of(context)!.errorUsernameNotFound;
return context.lang.errorUsernameNotFound;
case "UsernameNotValid":
return AppLocalizations.of(context)!.errorUsernameNotValid;
return context.lang.errorUsernameNotValid;
case "InvalidPublicKey":
return AppLocalizations.of(context)!.errorInvalidPublicKey;
return context.lang.errorInvalidPublicKey;
case "SessionAlreadyAuthenticated":
return AppLocalizations.of(context)!.errorSessionAlreadyAuthenticated;
return context.lang.errorSessionAlreadyAuthenticated;
case "SessionNotAuthenticated":
return AppLocalizations.of(context)!.errorSessionNotAuthenticated;
return context.lang.errorSessionNotAuthenticated;
case "OnlyOneSessionAllowed":
return AppLocalizations.of(context)!.errorOnlyOneSessionAllowed;
return context.lang.errorOnlyOneSessionAllowed;
default:
return code.toString(); // Fallback for unrecognized keys
}

View file

@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:camerawesome/camerawesome_plugin.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/components/image_editor/action_button.dart';
import 'package:twonly/src/components/media_view_sizing.dart';
import 'package:twonly/src/components/permissions_view.dart';
@ -176,6 +177,8 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
children: <Widget>[
ActionButton(
FontAwesomeIcons.repeat,
tooltipText:
context.lang.switchFrontAndBackCamera,
onPressed: () async {
cameraState.switchCameraSensor(
aspectRatio:
@ -185,6 +188,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
// SizedBox(height: 20),
ActionButton(
FontAwesomeIcons.bolt,
tooltipText: context.lang.toogleFlashLight,
color: isFlashOn
? const Color.fromARGB(255, 255, 230, 0)
: const Color.fromARGB(

View file

@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/src/components/image_editor/action_button.dart';
import 'package:twonly/src/components/media_view_sizing.dart';
import 'package:twonly/src/components/notification_badge.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/camera_to_share/share_image_view.dart';
import 'dart:async';
@ -27,6 +27,8 @@ class ShareImageEditorView extends StatefulWidget {
class _ShareImageEditorView extends State<ShareImageEditorView> {
bool _imageSaved = false;
bool _imageSaving = false;
bool _isRealTwonly = false;
int _maxShowTime = 18;
ImageItem currentImage = ImageItem();
ScreenshotController screenshotController = ScreenshotController();
@ -51,26 +53,31 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
return [];
}
return <Widget>[
BottomButton(
icon: FontAwesomeIcons.font,
onTap: () async {
ActionButton(
FontAwesomeIcons.font,
tooltipText: context.lang.addTextItem,
onPressed: () async {
undoLayers.clear();
removedLayers.clear();
layers.add(TextLayerData());
setState(() {});
},
),
BottomButton(
icon: FontAwesomeIcons.pencil,
onTap: () async {
const SizedBox(height: 8),
ActionButton(
FontAwesomeIcons.pencil,
tooltipText: context.lang.addDrawing,
onPressed: () async {
undoLayers.clear();
removedLayers.clear();
layers.add(DrawLayerData());
},
),
BottomButton(
icon: FontAwesomeIcons.faceGrinWide,
onTap: () async {
const SizedBox(height: 8),
ActionButton(
FontAwesomeIcons.faceGrinWide,
tooltipText: context.lang.addEmoji,
onPressed: () async {
EmojiLayerData? layer = await showModalBottomSheet(
context: context,
backgroundColor: Colors.black,
@ -78,16 +85,49 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
return const Emojis();
},
);
if (layer == null) return;
undoLayers.clear();
removedLayers.clear();
layers.add(layer);
setState(() {});
},
),
const SizedBox(height: 8),
NotificationBadge(
count: _maxShowTime == 999999 ? "" : _maxShowTime.toString(),
// count: "",
child: ActionButton(
FontAwesomeIcons.stopwatch,
tooltipText: context.lang.protectAsARealTwonly,
disable: _isRealTwonly,
onPressed: () async {
if (_maxShowTime == 999999) {
_maxShowTime = 4;
} else if (_maxShowTime >= 22) {
_maxShowTime = 999999;
} else {
_maxShowTime = _maxShowTime + 4;
}
// _maxShowTime =
// _isRealTwonly = !_isRealTwonly;
},
),
),
const SizedBox(height: 8),
ActionButton(
FontAwesomeIcons.shieldHeart,
tooltipText: context.lang.protectAsARealTwonly,
color: _isRealTwonly
? Theme.of(context).colorScheme.primary
: Colors.white,
onPressed: () async {
_isRealTwonly = !_isRealTwonly;
if (_isRealTwonly) {
_maxShowTime = 12;
}
},
),
];
}
@ -100,6 +140,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
return [
ActionButton(
FontAwesomeIcons.xmark,
tooltipText: context.lang.close,
onPressed: () async {
Navigator.pop(context);
},
@ -108,9 +149,8 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
const SizedBox(width: 8),
ActionButton(
FontAwesomeIcons.rotateLeft,
color: layers.length > 1 || removedLayers.isNotEmpty
? Colors.white
: Colors.grey,
tooltipText: context.lang.undo,
disable: layers.length <= 1 && removedLayers.isEmpty,
onPressed: () {
if (removedLayers.isNotEmpty) {
layers.add(removedLayers.removeLast());
@ -126,7 +166,8 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
const SizedBox(width: 8),
ActionButton(
FontAwesomeIcons.rotateRight,
color: undoLayers.isNotEmpty ? Colors.white : Colors.grey,
tooltipText: context.lang.redo,
disable: undoLayers.isEmpty,
onPressed: () {
if (undoLayers.isEmpty) return;
layers.add(undoLayers.removeLast());
@ -211,7 +252,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
),
),
Positioned(
right: 0,
right: 6,
top: 100,
child: Container(
alignment: Alignment.bottomCenter,
@ -266,10 +307,8 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
}
},
label: Text(_imageSaved
? AppLocalizations.of(context)!
.shareImagedEditorSavedImage
: AppLocalizations.of(context)!
.shareImagedEditorSaveImage),
? context.lang.shareImagedEditorSavedImage
: context.lang.shareImagedEditorSaveImage),
),
const SizedBox(width: 20),
FilledButton.icon(
@ -280,8 +319,12 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ShareImageView(imageBytes: imageBytes)),
builder: (context) => ShareImageView(
imageBytes: imageBytes,
isRealTwonly: _isRealTwonly,
maxShowTime: _maxShowTime,
),
),
);
},
style: ButtonStyle(
@ -290,7 +333,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
),
),
label: Text(
AppLocalizations.of(context)!.shareImagedEditorShareWith,
context.lang.shareImagedEditorShareWith,
style: TextStyle(fontSize: 17),
),
),
@ -302,57 +345,3 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
);
}
}
/// Button used in bottomNavigationBar in ImageEditor
class BottomButton extends StatelessWidget {
final VoidCallback? onTap, onLongPress;
final IconData icon;
final Color color;
const BottomButton({
super.key,
this.onTap,
this.color = Colors.white,
this.onLongPress,
required this.icon,
});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
onLongPress: onLongPress,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Column(
children: [
ActionButton(
icon,
color: color,
onPressed: onTap ?? () {},
),
const SizedBox(height: 8),
],
),
),
);
}
}
// /// Show image drawing surface over image
// class ImageEditorDrawing extends StatefulWidget {
// final ImageItem image;
// const ImageEditorDrawing({
// super.key,
// required this.image,
// });
// @override
// State<ImageEditorDrawing> createState() => _ImageEditorDrawingState();
// }
// class _ImageEditorDrawingState extends State<ImageEditorDrawing> {
// }
// }

View file

@ -2,7 +2,6 @@ import 'dart:collection';
import 'dart:typed_data';
import 'package:fixnum/fixnum.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/src/components/best_friends_selector.dart';
import 'package:twonly/src/components/flame.dart';
@ -14,8 +13,14 @@ import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/home_view.dart';
class ShareImageView extends StatefulWidget {
const ShareImageView({super.key, required this.imageBytes});
const ShareImageView(
{super.key,
required this.imageBytes,
required this.isRealTwonly,
required this.maxShowTime});
final Uint8List imageBytes;
final bool isRealTwonly;
final int maxShowTime;
@override
State<ShareImageView> createState() => _ShareImageView();
@ -92,11 +97,22 @@ class _ShareImageView extends State<ShareImageView> {
_updateUsers(usersFiltered);
}
void updateStatus(Int64 userId, bool checked) {
if (checked) {
if (widget.isRealTwonly) {
_selectedUserIds.clear();
}
_selectedUserIds.add(userId);
} else {
_selectedUserIds.remove(userId);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.shareImageTitle),
title: Text(context.lang.shareImageTitle),
),
body: Padding(
padding: EdgeInsets.only(bottom: 20, left: 10, top: 20, right: 10),
@ -106,30 +122,24 @@ class _ShareImageView extends State<ShareImageView> {
padding: EdgeInsets.symmetric(horizontal: 10),
child: TextField(
onChanged: _filterUsers,
decoration: getInputDecoration(context,
AppLocalizations.of(context)!.searchUsernameInput))),
decoration: getInputDecoration(
context, context.lang.searchUsernameInput))),
const SizedBox(height: 10),
BestFriendsSelector(
users: _bestFriends,
selectedUserIds: _selectedUserIds,
maxTotalMediaCounter: maxTotalMediaCounter,
updateStatus: (userId, checked) {
if (checked) {
_selectedUserIds.add(userId);
} else {
_selectedUserIds.remove(userId);
}
},
updateStatus: updateStatus,
),
const SizedBox(height: 10),
if (_otherUsers.isNotEmpty)
HeadLineComponent(
AppLocalizations.of(context)!.shareImageAllUsers),
HeadLineComponent(context.lang.shareImageAllUsers),
Expanded(
child: UserList(
List.from(_otherUsers),
maxTotalMediaCounter,
selectedUserIds: _selectedUserIds,
updateStatus: updateStatus,
),
)
],
@ -145,7 +155,12 @@ class _ShareImageView extends State<ShareImageView> {
FilledButton.icon(
icon: FaIcon(FontAwesomeIcons.solidPaperPlane),
onPressed: () async {
sendImage(_selectedUserIds.toList(), widget.imageBytes);
sendImage(
_selectedUserIds.toList(),
widget.imageBytes,
widget.isRealTwonly,
widget.maxShowTime,
);
// TODO: pop back to the HomeView page popUntil did not work. check later how to improve in case of pushing more then 2
Navigator.pop(context);
@ -158,7 +173,7 @@ class _ShareImageView extends State<ShareImageView> {
),
),
label: Text(
AppLocalizations.of(context)!.shareImagedEditorSendImage,
context.lang.shareImagedEditorSendImage,
style: TextStyle(fontSize: 17),
),
),
@ -172,7 +187,8 @@ class _ShareImageView extends State<ShareImageView> {
class UserList extends StatelessWidget {
const UserList(this.users, this.maxTotalMediaCounter,
{super.key, required this.selectedUserIds});
{super.key, required this.selectedUserIds, required this.updateStatus});
final Function(Int64, bool) updateStatus;
final List<Contact> users;
final int maxTotalMediaCounter;
final HashSet<Int64> selectedUserIds;
@ -201,19 +217,11 @@ class UserList extends StatelessWidget {
value: selectedUserIds.contains(user.userId),
onChanged: (bool? value) {
if (value == null) return;
if (value) {
selectedUserIds.add(user.userId);
} else {
selectedUserIds.remove(user.userId);
}
updateStatus(user.userId, value);
},
),
onTap: () {
if (!selectedUserIds.contains(user.userId)) {
selectedUserIds.add(user.userId);
} else {
selectedUserIds.remove(user.userId);
}
updateStatus(user.userId, !selectedUserIds.contains(user.userId));
},
);
},

View file

@ -10,7 +10,7 @@ import 'package:twonly/src/providers/api/api.dart';
import 'package:twonly/src/providers/download_change_provider.dart';
import 'package:twonly/src/providers/messages_change_provider.dart';
import 'package:twonly/src/views/chats/media_viewer_view.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:twonly/src/utils/misc.dart';
class ChatListEntry extends StatelessWidget {
const ChatListEntry(this.message, this.user, this.lastMessageFromSameUser,
@ -188,8 +188,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
}
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!
.chatListDetailTitle(widget.user.displayName)),
title: Text(context.lang.chatListDetailTitle(widget.user.displayName)),
),
body: Column(
children: [
@ -226,8 +225,7 @@ class _ChatItemDetailsViewState extends State<ChatItemDetailsView> {
_sendMessage();
},
decoration: InputDecoration(
hintText:
AppLocalizations.of(context)!.chatListDetailInput,
hintText: context.lang.chatListDetailInput,
contentPadding: EdgeInsets.symmetric(horizontal: 10)
// border: OutlineInputBorder(),
),

View file

@ -17,7 +17,6 @@ import 'package:twonly/src/views/home_view.dart';
import 'package:twonly/src/views/chats/media_viewer_view.dart';
import 'package:twonly/src/views/profile_view.dart';
import 'package:twonly/src/views/chats/search_username_view.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter/material.dart';
class ChatItem {
@ -86,7 +85,10 @@ class _ChatListViewState extends State<ChatListView> {
// title:
actions: [
NotificationBadge(
count: context.watch<ContactChangeProvider>().newContactRequests,
count: context
.watch<ContactChangeProvider>()
.newContactRequests
.toString(),
child: IconButton(
icon: FaIcon(FontAwesomeIcons.userPlus, size: 18),
onPressed: () {
@ -131,10 +133,8 @@ class _ChatListViewState extends State<ChatListView> {
: globalUpdateOfHomeViewPageIndex(1);
},
label: Text((activeUsers.isEmpty)
? AppLocalizations.of(context)!
.chatListViewSearchUserNameBtn
: AppLocalizations.of(context)!
.chatListViewSendFirstTwonly)),
? context.lang.chatListViewSearchUserNameBtn
: context.lang.chatListViewSendFirstTwonly)),
),
)
: ListView.builder(

View file

@ -1,6 +1,6 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:provider/provider.dart';
import 'package:twonly/main.dart';
import 'package:twonly/src/components/headline.dart';
@ -77,7 +77,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
return Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context)!.searchUsernameTitle),
title: Text(context.lang.searchUsernameTitle),
),
body: Padding(
padding: EdgeInsets.only(bottom: 20, left: 10, top: 20, right: 10),
@ -90,8 +90,8 @@ class _SearchUsernameView extends State<SearchUsernameView> {
_addNewUser(context);
},
controller: searchUserName,
decoration: getInputDecoration(
AppLocalizations.of(context)!.searchUsernameInput),
decoration:
getInputDecoration(context.lang.searchUsernameInput),
),
),
const SizedBox(height: 20),
@ -101,8 +101,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
showAlertDialog(context, "Coming soon",
"This feature is not yet implemented!");
},
label:
Text(AppLocalizations.of(context)!.searchUsernameQrCodeBtn),
label: Text(context.lang.searchUsernameQrCodeBtn),
),
SizedBox(height: 30),
if (context
@ -110,8 +109,7 @@ class _SearchUsernameView extends State<SearchUsernameView> {
.allContacts
.where((contact) => !contact.accepted)
.isNotEmpty)
HeadLineComponent(
AppLocalizations.of(context)!.searchUsernameNewFollowerTitle),
HeadLineComponent(context.lang.searchUsernameNewFollowerTitle),
Expanded(
child: ContactsListView(),
)

View file

@ -3,7 +3,6 @@ import 'package:logging/logging.dart';
import 'package:twonly/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:twonly/src/model/json/user_data.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/signal.dart';
@ -75,14 +74,14 @@ class _RegisterViewState extends State<RegisterView> {
children: [
const SizedBox(height: 50),
Text(
AppLocalizations.of(context)!.registerTitle,
context.lang.registerTitle,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 30),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 30),
child: Text(
AppLocalizations.of(context)!.registerSlogan,
context.lang.registerSlogan,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 12),
),
@ -92,7 +91,7 @@ class _RegisterViewState extends State<RegisterView> {
child: Padding(
padding: EdgeInsets.only(left: 10, right: 10),
child: Text(
AppLocalizations.of(context)!.registerUsernameSlogan,
context.lang.registerUsernameSlogan,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15),
),
@ -107,7 +106,7 @@ class _RegisterViewState extends State<RegisterView> {
],
style: TextStyle(fontSize: 17),
decoration: getInputDecoration(
AppLocalizations.of(context)!.registerUsernameDecoration,
context.lang.registerUsernameDecoration,
),
),
const SizedBox(height: 5),
@ -115,7 +114,7 @@ class _RegisterViewState extends State<RegisterView> {
child: Padding(
padding: EdgeInsets.only(left: 10, right: 10),
child: Text(
AppLocalizations.of(context)!.registerUsernameLimits,
context.lang.registerUsernameLimits,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 7),
),
@ -166,7 +165,7 @@ class _RegisterViewState extends State<RegisterView> {
Colors.grey)
: null),
label: Text(
AppLocalizations.of(context)!.registerSubmitButton,
context.lang.registerSubmitButton,
style: TextStyle(fontSize: 17),
),
),