Merge pull request 'Prevent Layout Errors Caused By Pathological Unicode' (#631) from unicode into trunk
continuous-integration/drone/push Build is pending Details

Reviewed-on: #631
Reviewed-by: Dan Ballard <dan@openprivacy.ca>
This commit is contained in:
Sarah Jamie Lewis 2023-02-17 00:06:01 +00:00
commit 107281e20a
20 changed files with 190 additions and 157 deletions

View File

@ -138,17 +138,6 @@ steps:
- cd .. - cd ..
- scp -r -o StrictHostKeyChecking=no -i ~/id_rsa $DIR buildfiles@build.openprivacy.ca:/home/buildfiles/buildfiles/ - scp -r -o StrictHostKeyChecking=no -i ~/id_rsa $DIR buildfiles@build.openprivacy.ca:/home/buildfiles/buildfiles/
- name: notify-email
image: drillster/drone-email
pull: if-not-exists
settings:
host: build.openprivacy.ca
port: 25
skip_verify: true
from: drone@openprivacy.ca
when:
status: [ failure ]
- name: notify-gogs - name: notify-gogs
image: openpriv/drone-gogs image: openpriv/drone-gogs
pull: if-not-exists pull: if-not-exists

View File

@ -159,7 +159,6 @@ class CwtchFfi implements Cwtch {
cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, ".cwtch"); cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, ".cwtch");
} }
if (await File("linux/Tor/tor").exists()) { if (await File("linux/Tor/tor").exists()) {
bundledTor = "linux/Tor/tor"; bundledTor = "linux/Tor/tor";
} else if (await File("lib/Tor/tor").exists()) { } else if (await File("lib/Tor/tor").exists()) {
@ -788,7 +787,6 @@ class CwtchFfi implements Cwtch {
@override @override
String? defaultDownloadPath() { String? defaultDownloadPath() {
Map<String, String> envVars = Platform.environment; Map<String, String> envVars = Platform.environment;
String nominalPath = path.join(envVars[Platform.isWindows ? 'UserProfile' : 'HOME']!, "Downloads"); String nominalPath = path.join(envVars[Platform.isWindows ? 'UserProfile' : 'HOME']!, "Downloads");
if (Directory(nominalPath).existsSync() == false) { if (Directory(nominalPath).existsSync() == false) {

View File

@ -71,7 +71,6 @@ class FlwtchState extends State<Flwtch> with WindowListener {
@override @override
initState() { initState() {
globalSettings = Settings(Locale("en", ''), CwtchDark()); globalSettings = Settings(Locale("en", ''), CwtchDark());
globalErrorHandler = ErrorHandler(); globalErrorHandler = ErrorHandler();
globalTorStatus = TorStatus(); globalTorStatus = TorStatus();
@ -204,7 +203,8 @@ class FlwtchState extends State<Flwtch> with WindowListener {
print("Exiting..."); print("Exiting...");
exit(0); exit(0);
} }
}; }
;
} }
// Invoked via notificationClickChannel by MyBroadcastReceiver in MainActivity.kt // Invoked via notificationClickChannel by MyBroadcastReceiver in MainActivity.kt

View File

@ -69,5 +69,4 @@ class ProfileServerListState extends ChangeNotifier {
} }
List<RemoteServerInfoState> get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier List<RemoteServerInfoState> get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier
} }

View File

@ -68,7 +68,6 @@ class ServerListState extends ChangeNotifier {
} }
List<ServerInfoState> get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier List<ServerInfoState> get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier
} }
class ServerInfoState extends ChangeNotifier { class ServerInfoState extends ChangeNotifier {

View File

@ -154,7 +154,6 @@ class NixNotificationManager implements NotificationsManager {
} }
NotificationsManager newDesktopNotificationsManager(Future<void> Function(String profileOnion, int convoId) notificationSelectConvo) { NotificationsManager newDesktopNotificationsManager(Future<void> Function(String profileOnion, int convoId) notificationSelectConvo) {
// We don't want notifications in Dev Mode // We don't want notifications in Dev Mode
if (EnvironmentConfig.TEST_MODE) { if (EnvironmentConfig.TEST_MODE) {
return NullNotificationsManager(); return NullNotificationsManager();

View File

@ -294,7 +294,10 @@ class SelectableLinkify extends StatelessWidget {
linkifiers: linkifiers, linkifiers: linkifiers,
); );
return SelectableText.rich( return Container(
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(),
child: SelectableText.rich(
buildTextSpan( buildTextSpan(
elements, elements,
style: Theme.of(context).textTheme.bodyText2?.merge(style), style: Theme.of(context).textTheme.bodyText2?.merge(style),
@ -334,7 +337,7 @@ class SelectableLinkify extends StatelessWidget {
selectionControls: selectionControls, selectionControls: selectionControls,
onSelectionChanged: onSelectionChanged, onSelectionChanged: onSelectionChanged,
style: style, style: style,
); ));
} }
} }

View File

@ -46,7 +46,11 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(Provider.of<ContactInfoState>(context).nickname + " " + AppLocalizations.of(context)!.conversationSettings), title: Container(
height: 24,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(),
child: Text(Provider.of<ContactInfoState>(context).nickname + " " + AppLocalizations.of(context)!.conversationSettings)),
), ),
body: _buildSettingsList(), body: _buildSettingsList(),
); );

View File

@ -1,5 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:math';
import 'dart:ui'; import 'dart:ui';
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:cwtch/cwtch/cwtch.dart'; import 'package:cwtch/cwtch/cwtch.dart';
@ -208,10 +209,15 @@ class _MessageViewState extends State<MessageView> {
width: 10, width: 10,
), ),
Expanded( Expanded(
child: Container(
height: 24,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(),
child: Text( child: Text(
Provider.of<ContactInfoState>(context).nickname, Provider.of<ContactInfoState>(context).nickname,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.clip,
)) maxLines: 1,
)))
]), ]),
actions: appBarButtons, actions: appBarButtons,
), ),
@ -574,7 +580,7 @@ class _MessageViewState extends State<MessageView> {
keyboardType: TextInputType.multiline, keyboardType: TextInputType.multiline,
enableIMEPersonalizedLearning: false, enableIMEPersonalizedLearning: false,
minLines: 1, minLines: 1,
maxLength: (isGroup ? GroupMessageLengthMax : P2PMessageLengthMax) - numberOfBytesMoreThanChar, maxLength: max(1, (isGroup ? GroupMessageLengthMax : P2PMessageLengthMax) - numberOfBytesMoreThanChar),
maxLengthEnforcement: MaxLengthEnforcement.enforced, maxLengthEnforcement: MaxLengthEnforcement.enforced,
maxLines: 3, maxLines: 3,
onFieldSubmitted: _sendMessage, onFieldSubmitted: _sendMessage,

View File

@ -47,7 +47,7 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
} }
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(handle + " " + AppLocalizations.of(context)!.conversationSettings), title: Container(height: 24, clipBehavior: Clip.hardEdge, decoration: BoxDecoration(), child: Text(handle + " " + AppLocalizations.of(context)!.conversationSettings)),
), ),
body: _buildSettingsList(), body: _buildSettingsList(),
); );

View File

@ -44,7 +44,10 @@ class _CwtchButtonTextFieldState extends State<CwtchButtonTextField> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<Settings>(builder: (context, theme, child) { return Consumer<Settings>(builder: (context, theme, child) {
return TextFormField( return Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(),
child: TextFormField(
key: widget.testKey, key: widget.testKey,
controller: widget.controller, controller: widget.controller,
readOnly: widget.readonly, readOnly: widget.readonly,
@ -52,6 +55,8 @@ class _CwtchButtonTextFieldState extends State<CwtchButtonTextField> {
focusNode: _focusNode, focusNode: _focusNode,
enableIMEPersonalizedLearning: false, enableIMEPersonalizedLearning: false,
onChanged: widget.onChanged, onChanged: widget.onChanged,
maxLines: 1,
style: TextStyle(overflow: TextOverflow.clip),
decoration: InputDecoration( decoration: InputDecoration(
labelText: widget.labelText, labelText: widget.labelText,
labelStyle: TextStyle(color: theme.current().mainTextColor, backgroundColor: theme.current().textfieldBackgroundColor), labelStyle: TextStyle(color: theme.current().mainTextColor, backgroundColor: theme.current().textfieldBackgroundColor),
@ -79,7 +84,7 @@ class _CwtchButtonTextFieldState extends State<CwtchButtonTextField> {
), ),
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0), contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 1.0))), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 1.0))),
); ));
}); });
} }
} }

View File

@ -64,7 +64,11 @@ class _ContactRowState extends State<ContactRow> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Container(
height: 24,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(),
child: Text(
contact.nickname, //(contact.isInvitation ? "invite " : "non-invite ") + (contact.isBlocked ? "blokt" : "nonblokt"),// contact.nickname, //(contact.isInvitation ? "invite " : "non-invite ") + (contact.isBlocked ? "blokt" : "nonblokt"),//
style: TextStyle( style: TextStyle(
@ -73,8 +77,9 @@ class _ContactRowState extends State<ContactRow> {
? Provider.of<Settings>(context).theme.portraitBlockedTextColor ? Provider.of<Settings>(context).theme.portraitBlockedTextColor
: Provider.of<Settings>(context).theme.mainTextColor), //Provider.of<FlwtchState>(context).biggerFont, : Provider.of<Settings>(context).theme.mainTextColor), //Provider.of<FlwtchState>(context).biggerFont,
softWrap: true, softWrap: true,
overflow: TextOverflow.visible, overflow: TextOverflow.clip,
), maxLines: 1,
)),
syncStatus ?? Container(), syncStatus ?? Container(),
Visibility( Visibility(
visible: !Provider.of<Settings>(context).streamerMode, visible: !Provider.of<Settings>(context).streamerMode,

View File

@ -144,8 +144,12 @@ class FileBubbleState extends State<FileBubble> {
return LayoutBuilder(builder: (bcontext, constraints) { return LayoutBuilder(builder: (bcontext, constraints) {
var wdgSender = Visibility( var wdgSender = Visibility(
visible: widget.interactive, visible: widget.interactive,
child: Container(
height: 11,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(),
child: SelectableText(senderDisplayStr + '\u202F', child: SelectableText(senderDisplayStr + '\u202F',
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor))); style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor))));
var isPreview = false; var isPreview = false;
var wdgMessage = !showFileSharing var wdgMessage = !showFileSharing
? Text(AppLocalizations.of(context)!.messageEnableFileSharing) ? Text(AppLocalizations.of(context)!.messageEnableFileSharing)

View File

@ -42,8 +42,17 @@ class MessageBubbleState extends State<MessageBubble> {
senderDisplayStr = Provider.of<MessageMetadata>(context).senderHandle; senderDisplayStr = Provider.of<MessageMetadata>(context).senderHandle;
} }
} }
var wdgSender = SelectableText(senderDisplayStr, var wdgSender = Container(
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)); height: 11,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(),
child: SelectableText(senderDisplayStr,
maxLines: 1,
style: TextStyle(
fontSize: 9.0,
overflow: TextOverflow.clip,
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor,
)));
var wdgMessage = SelectableLinkify( var wdgMessage = SelectableLinkify(
text: widget.content + '\u202F', text: widget.content + '\u202F',

View File

@ -44,13 +44,17 @@ class _ProfileRowState extends State<ProfileRow> {
Expanded( Expanded(
child: Column( child: Column(
children: [ children: [
Text( Container(
height: 24,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(),
child: Text(
profile.nickname, profile.nickname,
semanticsLabel: profile.nickname, semanticsLabel: profile.nickname,
style: Provider.of<FlwtchState>(context).biggerFont, style: Provider.of<FlwtchState>(context).biggerFont,
softWrap: true, softWrap: true,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), )),
Visibility( Visibility(
visible: !Provider.of<Settings>(context).streamerMode, visible: !Provider.of<Settings>(context).streamerMode,
child: ExcludeSemantics( child: ExcludeSemantics(

View File

@ -43,8 +43,12 @@ class QuotedMessageBubbleState extends State<QuotedMessageBubble> {
} }
} }
var wdgSender = SelectableText(senderDisplayStr, var wdgSender = Container(
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)); height: 11,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(),
child: SelectableText(senderDisplayStr,
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor : Provider.of<Settings>(context).theme.messageFromOtherTextColor)));
var showClickableLinks = Provider.of<Settings>(context).isExperimentEnabled(ClickableLinksExperiment); var showClickableLinks = Provider.of<Settings>(context).isExperimentEnabled(ClickableLinksExperiment);
var formatMessages = Provider.of<Settings>(context).isExperimentEnabled(FormattingExperiment); var formatMessages = Provider.of<Settings>(context).isExperimentEnabled(FormattingExperiment);

View File

@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -42,7 +43,10 @@ class _CwtchTextFieldState extends State<CwtchTextField> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<Settings>(builder: (context, theme, child) { return Consumer<Settings>(builder: (context, theme, child) {
return TextFormField( return Container(
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(),
child: TextFormField(
key: widget.testKey, key: widget.testKey,
controller: widget.controller, controller: widget.controller,
validator: widget.validator, validator: widget.validator,
@ -60,6 +64,7 @@ class _CwtchTextFieldState extends State<CwtchTextField> {
scrollController: _scrollController, scrollController: _scrollController,
enableIMEPersonalizedLearning: false, enableIMEPersonalizedLearning: false,
focusNode: _focusNode, focusNode: _focusNode,
style: TextStyle(overflow: TextOverflow.clip),
decoration: InputDecoration( decoration: InputDecoration(
errorMaxLines: 2, errorMaxLines: 2,
hintText: widget.hintText, hintText: widget.hintText,
@ -72,7 +77,7 @@ class _CwtchTextFieldState extends State<CwtchTextField> {
fillColor: theme.current().textfieldBackgroundColor, fillColor: theme.current().textfieldBackgroundColor,
contentPadding: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0), contentPadding: EdgeInsets.fromLTRB(10.0, 5.0, 10.0, 5.0),
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 1.0))), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 1.0))),
); ));
}); });
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB