From af2815957d4801a26df2f24e28a812f1e23c1883 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 16 Feb 2023 13:46:48 -0800 Subject: [PATCH 1/3] Prevent Layout Errors Caused By Pathological Unicode --- lib/cwtch/ffi.dart | 2 - lib/main.dart | 4 +- lib/models/profileservers.dart | 1 - lib/models/servers.dart | 1 - lib/notification_manager.dart | 1 - lib/third_party/linkify/flutter_linkify.dart | 85 ++++++++++---------- lib/views/globalsettingsview.dart | 2 +- lib/views/groupsettingsview.dart | 6 +- lib/views/messageview.dart | 16 ++-- lib/views/peersettingsview.dart | 2 +- lib/widgets/buttontextfield.dart | 77 +++++++++--------- lib/widgets/contactrow.dart | 25 +++--- lib/widgets/filebubble.dart | 8 +- lib/widgets/messagebubble.dart | 13 ++- lib/widgets/profilerow.dart | 18 +++-- lib/widgets/quotedmessage.dart | 8 +- lib/widgets/textfield.dart | 67 ++++++++------- 17 files changed, 190 insertions(+), 146 deletions(-) diff --git a/lib/cwtch/ffi.dart b/lib/cwtch/ffi.dart index f6aa14f5..c7b6b45f 100644 --- a/lib/cwtch/ffi.dart +++ b/lib/cwtch/ffi.dart @@ -159,7 +159,6 @@ class CwtchFfi implements Cwtch { cwtchDir = envVars['CWTCH_HOME'] ?? path.join(envVars['HOME']!, ".cwtch"); } - if (await File("linux/Tor/tor").exists()) { bundledTor = "linux/Tor/tor"; } else if (await File("lib/Tor/tor").exists()) { @@ -788,7 +787,6 @@ class CwtchFfi implements Cwtch { @override String? defaultDownloadPath() { - Map envVars = Platform.environment; String nominalPath = path.join(envVars[Platform.isWindows ? 'UserProfile' : 'HOME']!, "Downloads"); if (Directory(nominalPath).existsSync() == false) { diff --git a/lib/main.dart b/lib/main.dart index cfbf9dd6..180ffae7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -71,7 +71,6 @@ class FlwtchState extends State with WindowListener { @override initState() { - globalSettings = Settings(Locale("en", ''), CwtchDark()); globalErrorHandler = ErrorHandler(); globalTorStatus = TorStatus(); @@ -204,7 +203,8 @@ class FlwtchState extends State with WindowListener { print("Exiting..."); exit(0); } - }; + } + ; } // Invoked via notificationClickChannel by MyBroadcastReceiver in MainActivity.kt diff --git a/lib/models/profileservers.dart b/lib/models/profileservers.dart index fbc02203..61ee76d1 100644 --- a/lib/models/profileservers.dart +++ b/lib/models/profileservers.dart @@ -69,5 +69,4 @@ class ProfileServerListState extends ChangeNotifier { } List get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier - } diff --git a/lib/models/servers.dart b/lib/models/servers.dart index cd059cbf..c08290fd 100644 --- a/lib/models/servers.dart +++ b/lib/models/servers.dart @@ -68,7 +68,6 @@ class ServerListState extends ChangeNotifier { } List get servers => _servers.sublist(0); //todo: copy?? dont want caller able to bypass changenotifier - } class ServerInfoState extends ChangeNotifier { diff --git a/lib/notification_manager.dart b/lib/notification_manager.dart index f5cb9e8b..00042bcc 100644 --- a/lib/notification_manager.dart +++ b/lib/notification_manager.dart @@ -154,7 +154,6 @@ class NixNotificationManager implements NotificationsManager { } NotificationsManager newDesktopNotificationsManager(Future Function(String profileOnion, int convoId) notificationSelectConvo) { - // We don't want notifications in Dev Mode if (EnvironmentConfig.TEST_MODE) { return NullNotificationsManager(); diff --git a/lib/third_party/linkify/flutter_linkify.dart b/lib/third_party/linkify/flutter_linkify.dart index a4c38881..882bdfe5 100644 --- a/lib/third_party/linkify/flutter_linkify.dart +++ b/lib/third_party/linkify/flutter_linkify.dart @@ -294,47 +294,50 @@ class SelectableLinkify extends StatelessWidget { linkifiers: linkifiers, ); - return SelectableText.rich( - buildTextSpan( - elements, - style: Theme.of(context).textTheme.bodyText2?.merge(style), - codeStyle: Theme.of(context).textTheme.bodyText2?.merge(codeStyle), - onOpen: onOpen, - context: context, - linkStyle: Theme.of(context) - .textTheme - .bodyText2 - ?.merge(style) - .copyWith( - color: Colors.blueAccent, - decoration: TextDecoration.underline, - ) - .merge(linkStyle), - ), - textAlign: textAlign, - textDirection: textDirection, - minLines: minLines, - maxLines: maxLines, - focusNode: focusNode, - strutStyle: strutStyle, - showCursor: showCursor, - textScaleFactor: textScaleFactor, - autofocus: autofocus, - toolbarOptions: toolbarOptions, - cursorWidth: cursorWidth, - cursorRadius: cursorRadius, - cursorColor: cursorColor, - dragStartBehavior: dragStartBehavior, - enableInteractiveSelection: enableInteractiveSelection, - onTap: onTap, - scrollPhysics: scrollPhysics, - textWidthBasis: textWidthBasis, - textHeightBehavior: textHeightBehavior, - cursorHeight: cursorHeight, - selectionControls: selectionControls, - onSelectionChanged: onSelectionChanged, - style: style, - ); + return Container( + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(), + child: SelectableText.rich( + buildTextSpan( + elements, + style: Theme.of(context).textTheme.bodyText2?.merge(style), + codeStyle: Theme.of(context).textTheme.bodyText2?.merge(codeStyle), + onOpen: onOpen, + context: context, + linkStyle: Theme.of(context) + .textTheme + .bodyText2 + ?.merge(style) + .copyWith( + color: Colors.blueAccent, + decoration: TextDecoration.underline, + ) + .merge(linkStyle), + ), + textAlign: textAlign, + textDirection: textDirection, + minLines: minLines, + maxLines: maxLines, + focusNode: focusNode, + strutStyle: strutStyle, + showCursor: showCursor, + textScaleFactor: textScaleFactor, + autofocus: autofocus, + toolbarOptions: toolbarOptions, + cursorWidth: cursorWidth, + cursorRadius: cursorRadius, + cursorColor: cursorColor, + dragStartBehavior: dragStartBehavior, + enableInteractiveSelection: enableInteractiveSelection, + onTap: onTap, + scrollPhysics: scrollPhysics, + textWidthBasis: textWidthBasis, + textHeightBehavior: textHeightBehavior, + cursorHeight: cursorHeight, + selectionControls: selectionControls, + onSelectionChanged: onSelectionChanged, + style: style, + )); } } diff --git a/lib/views/globalsettingsview.dart b/lib/views/globalsettingsview.dart index a8306250..97e08748 100644 --- a/lib/views/globalsettingsview.dart +++ b/lib/views/globalsettingsview.dart @@ -128,7 +128,7 @@ class _GlobalSettingsViewState extends State { items: AppLocalizations.supportedLocales.map>((Locale value) { return DropdownMenuItem( value: value.toString(), - child: Text( key: Key("dropdownLanguage" + value.languageCode), getLanguageFull(context, value.languageCode, value.countryCode)), + child: Text(key: Key("dropdownLanguage" + value.languageCode), getLanguageFull(context, value.languageCode, value.countryCode)), ); }).toList()))), SwitchListTile( diff --git a/lib/views/groupsettingsview.dart b/lib/views/groupsettingsview.dart index 65048f7d..492c0847 100644 --- a/lib/views/groupsettingsview.dart +++ b/lib/views/groupsettingsview.dart @@ -46,7 +46,11 @@ class _GroupSettingsViewState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(Provider.of(context).nickname + " " + AppLocalizations.of(context)!.conversationSettings), + title: Container( + height: 24, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(), + child: Text(Provider.of(context).nickname + " " + AppLocalizations.of(context)!.conversationSettings)), ), body: _buildSettingsList(), ); diff --git a/lib/views/messageview.dart b/lib/views/messageview.dart index f74f9f93..868d1f70 100644 --- a/lib/views/messageview.dart +++ b/lib/views/messageview.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'dart:io'; +import 'dart:math'; import 'dart:ui'; import 'package:crypto/crypto.dart'; import 'package:cwtch/cwtch/cwtch.dart'; @@ -208,10 +209,15 @@ class _MessageViewState extends State { width: 10, ), Expanded( - child: Text( - Provider.of(context).nickname, - overflow: TextOverflow.ellipsis, - )) + child: Container( + height: 24, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(), + child: Text( + Provider.of(context).nickname, + overflow: TextOverflow.clip, + maxLines: 1, + ))) ]), actions: appBarButtons, ), @@ -574,7 +580,7 @@ class _MessageViewState extends State { keyboardType: TextInputType.multiline, enableIMEPersonalizedLearning: false, minLines: 1, - maxLength: (isGroup ? GroupMessageLengthMax : P2PMessageLengthMax) - numberOfBytesMoreThanChar, + maxLength: max(1, (isGroup ? GroupMessageLengthMax : P2PMessageLengthMax) - numberOfBytesMoreThanChar), maxLengthEnforcement: MaxLengthEnforcement.enforced, maxLines: 3, onFieldSubmitted: _sendMessage, diff --git a/lib/views/peersettingsview.dart b/lib/views/peersettingsview.dart index d4ae50c0..35ec44e2 100644 --- a/lib/views/peersettingsview.dart +++ b/lib/views/peersettingsview.dart @@ -47,7 +47,7 @@ class _PeerSettingsViewState extends State { } return Scaffold( 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(), ); diff --git a/lib/widgets/buttontextfield.dart b/lib/widgets/buttontextfield.dart index dd695de2..b5c24847 100644 --- a/lib/widgets/buttontextfield.dart +++ b/lib/widgets/buttontextfield.dart @@ -44,42 +44,47 @@ class _CwtchButtonTextFieldState extends State { @override Widget build(BuildContext context) { return Consumer(builder: (context, theme, child) { - return TextFormField( - key: widget.testKey, - controller: widget.controller, - readOnly: widget.readonly, - showCursor: !widget.readonly, - focusNode: _focusNode, - enableIMEPersonalizedLearning: false, - onChanged: widget.onChanged, - decoration: InputDecoration( - labelText: widget.labelText, - labelStyle: TextStyle(color: theme.current().mainTextColor, backgroundColor: theme.current().textfieldBackgroundColor), - suffixIcon: IconButton( - onPressed: widget.onPressed, - icon: widget.icon, - splashRadius: Material.defaultSplashRadius / 2, - padding: EdgeInsets.fromLTRB(0.0, 4.0, 2.0, 2.0), - tooltip: widget.tooltip, - enableFeedback: true, - color: theme.current().mainTextColor, - highlightColor: theme.current().defaultButtonColor, - focusColor: theme.current().defaultButtonActiveColor, - splashColor: theme.current().defaultButtonActiveColor, - ), - floatingLabelBehavior: FloatingLabelBehavior.never, - filled: true, - fillColor: theme.current().textfieldBackgroundColor, - focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 1.0)), - focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 1.0)), - errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 1.0)), - errorStyle: TextStyle( - color: theme.current().textfieldErrorColor, - fontWeight: FontWeight.bold, - ), - 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))), - ); + return Container( + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(), + child: TextFormField( + key: widget.testKey, + controller: widget.controller, + readOnly: widget.readonly, + showCursor: !widget.readonly, + focusNode: _focusNode, + enableIMEPersonalizedLearning: false, + onChanged: widget.onChanged, + maxLines: 1, + style: TextStyle(overflow: TextOverflow.clip), + decoration: InputDecoration( + labelText: widget.labelText, + labelStyle: TextStyle(color: theme.current().mainTextColor, backgroundColor: theme.current().textfieldBackgroundColor), + suffixIcon: IconButton( + onPressed: widget.onPressed, + icon: widget.icon, + splashRadius: Material.defaultSplashRadius / 2, + padding: EdgeInsets.fromLTRB(0.0, 4.0, 2.0, 2.0), + tooltip: widget.tooltip, + enableFeedback: true, + color: theme.current().mainTextColor, + highlightColor: theme.current().defaultButtonColor, + focusColor: theme.current().defaultButtonActiveColor, + splashColor: theme.current().defaultButtonActiveColor, + ), + floatingLabelBehavior: FloatingLabelBehavior.never, + filled: true, + fillColor: theme.current().textfieldBackgroundColor, + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 1.0)), + focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 1.0)), + errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 1.0)), + errorStyle: TextStyle( + color: theme.current().textfieldErrorColor, + fontWeight: FontWeight.bold, + ), + 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))), + )); }); } } diff --git a/lib/widgets/contactrow.dart b/lib/widgets/contactrow.dart index 66332612..8411214b 100644 --- a/lib/widgets/contactrow.dart +++ b/lib/widgets/contactrow.dart @@ -64,17 +64,22 @@ class _ContactRowState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - contact.nickname, //(contact.isInvitation ? "invite " : "non-invite ") + (contact.isBlocked ? "blokt" : "nonblokt"),// + Container( + height: 24, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(), + child: Text( + contact.nickname, //(contact.isInvitation ? "invite " : "non-invite ") + (contact.isBlocked ? "blokt" : "nonblokt"),// - style: TextStyle( - fontSize: Provider.of(context).theme.contactOnionTextSize(), - color: contact.isBlocked - ? Provider.of(context).theme.portraitBlockedTextColor - : Provider.of(context).theme.mainTextColor), //Provider.of(context).biggerFont, - softWrap: true, - overflow: TextOverflow.visible, - ), + style: TextStyle( + fontSize: Provider.of(context).theme.contactOnionTextSize(), + color: contact.isBlocked + ? Provider.of(context).theme.portraitBlockedTextColor + : Provider.of(context).theme.mainTextColor), //Provider.of(context).biggerFont, + softWrap: true, + overflow: TextOverflow.clip, + maxLines: 1, + )), syncStatus ?? Container(), Visibility( visible: !Provider.of(context).streamerMode, diff --git a/lib/widgets/filebubble.dart b/lib/widgets/filebubble.dart index 0b98423f..e1181414 100644 --- a/lib/widgets/filebubble.dart +++ b/lib/widgets/filebubble.dart @@ -144,8 +144,12 @@ class FileBubbleState extends State { return LayoutBuilder(builder: (bcontext, constraints) { var wdgSender = Visibility( visible: widget.interactive, - child: SelectableText(senderDisplayStr + '\u202F', - style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of(context).theme.messageFromMeTextColor : Provider.of(context).theme.messageFromOtherTextColor))); + child: Container( + height: 11, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(), + child: SelectableText(senderDisplayStr + '\u202F', + style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of(context).theme.messageFromMeTextColor : Provider.of(context).theme.messageFromOtherTextColor)))); var isPreview = false; var wdgMessage = !showFileSharing ? Text(AppLocalizations.of(context)!.messageEnableFileSharing) diff --git a/lib/widgets/messagebubble.dart b/lib/widgets/messagebubble.dart index 19e7a103..531f1a5a 100644 --- a/lib/widgets/messagebubble.dart +++ b/lib/widgets/messagebubble.dart @@ -42,8 +42,17 @@ class MessageBubbleState extends State { senderDisplayStr = Provider.of(context).senderHandle; } } - var wdgSender = SelectableText(senderDisplayStr, - style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of(context).theme.messageFromMeTextColor : Provider.of(context).theme.messageFromOtherTextColor)); + var wdgSender = Container( + height: 11, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(), + child: SelectableText(senderDisplayStr, + maxLines: 1, + style: TextStyle( + fontSize: 9.0, + overflow: TextOverflow.clip, + color: fromMe ? Provider.of(context).theme.messageFromMeTextColor : Provider.of(context).theme.messageFromOtherTextColor, + ))); var wdgMessage = SelectableLinkify( text: widget.content + '\u202F', diff --git a/lib/widgets/profilerow.dart b/lib/widgets/profilerow.dart index dfc362b0..f08ac334 100644 --- a/lib/widgets/profilerow.dart +++ b/lib/widgets/profilerow.dart @@ -44,13 +44,17 @@ class _ProfileRowState extends State { Expanded( child: Column( children: [ - Text( - profile.nickname, - semanticsLabel: profile.nickname, - style: Provider.of(context).biggerFont, - softWrap: true, - overflow: TextOverflow.ellipsis, - ), + Container( + height: 24, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(), + child: Text( + profile.nickname, + semanticsLabel: profile.nickname, + style: Provider.of(context).biggerFont, + softWrap: true, + overflow: TextOverflow.ellipsis, + )), Visibility( visible: !Provider.of(context).streamerMode, child: ExcludeSemantics( diff --git a/lib/widgets/quotedmessage.dart b/lib/widgets/quotedmessage.dart index d371d3e8..810342bb 100644 --- a/lib/widgets/quotedmessage.dart +++ b/lib/widgets/quotedmessage.dart @@ -43,8 +43,12 @@ class QuotedMessageBubbleState extends State { } } - var wdgSender = SelectableText(senderDisplayStr, - style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of(context).theme.messageFromMeTextColor : Provider.of(context).theme.messageFromOtherTextColor)); + var wdgSender = Container( + height: 11, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration(), + child: SelectableText(senderDisplayStr, + style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of(context).theme.messageFromMeTextColor : Provider.of(context).theme.messageFromOtherTextColor))); var showClickableLinks = Provider.of(context).isExperimentEnabled(ClickableLinksExperiment); var formatMessages = Provider.of(context).isExperimentEnabled(FormattingExperiment); diff --git a/lib/widgets/textfield.dart b/lib/widgets/textfield.dart index 0a9ffa6d..9c77280f 100644 --- a/lib/widgets/textfield.dart +++ b/lib/widgets/textfield.dart @@ -1,3 +1,4 @@ +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; @@ -42,37 +43,41 @@ class _CwtchTextFieldState extends State { @override Widget build(BuildContext context) { return Consumer(builder: (context, theme, child) { - return TextFormField( - key: widget.testKey, - controller: widget.controller, - validator: widget.validator, - onChanged: widget.onChanged, - autofocus: widget.autofocus, - autovalidateMode: AutovalidateMode.onUserInteraction, - textAlign: widget.number ? TextAlign.end : TextAlign.start, - keyboardType: widget.multiLine - ? TextInputType.multiline - : widget.number - ? TextInputType.number - : TextInputType.text, - inputFormatters: widget.number ? [FilteringTextInputFormatter.digitsOnly] : null, - maxLines: widget.multiLine ? null : 1, - scrollController: _scrollController, - enableIMEPersonalizedLearning: false, - focusNode: _focusNode, - decoration: InputDecoration( - errorMaxLines: 2, - hintText: widget.hintText, - floatingLabelBehavior: FloatingLabelBehavior.never, - filled: true, - focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 1.0)), - focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 1.0)), - errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 1.0)), - errorStyle: TextStyle(color: theme.current().textfieldErrorColor, fontWeight: FontWeight.bold, overflow: TextOverflow.visible), - fillColor: theme.current().textfieldBackgroundColor, - 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))), - ); + return Container( + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration(), + child: TextFormField( + key: widget.testKey, + controller: widget.controller, + validator: widget.validator, + onChanged: widget.onChanged, + autofocus: widget.autofocus, + autovalidateMode: AutovalidateMode.onUserInteraction, + textAlign: widget.number ? TextAlign.end : TextAlign.start, + keyboardType: widget.multiLine + ? TextInputType.multiline + : widget.number + ? TextInputType.number + : TextInputType.text, + inputFormatters: widget.number ? [FilteringTextInputFormatter.digitsOnly] : null, + maxLines: widget.multiLine ? null : 1, + scrollController: _scrollController, + enableIMEPersonalizedLearning: false, + focusNode: _focusNode, + style: TextStyle(overflow: TextOverflow.clip), + decoration: InputDecoration( + errorMaxLines: 2, + hintText: widget.hintText, + floatingLabelBehavior: FloatingLabelBehavior.never, + filled: true, + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldBorderColor, width: 1.0)), + focusedErrorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 1.0)), + errorBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(6.0), borderSide: BorderSide(color: theme.current().textfieldErrorColor, width: 1.0)), + errorStyle: TextStyle(color: theme.current().textfieldErrorColor, fontWeight: FontWeight.bold, overflow: TextOverflow.visible), + fillColor: theme.current().textfieldBackgroundColor, + 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))), + )); }); } } From ffe3da6c4ee036fca8bd9d9a8195ee72d34db6bc Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 16 Feb 2023 13:48:47 -0800 Subject: [PATCH 2/3] Remove Email Step from Drone --- .drone.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.drone.yml b/.drone.yml index 0fd09e19..32448aec 100644 --- a/.drone.yml +++ b/.drone.yml @@ -138,17 +138,6 @@ steps: - cd .. - 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 image: openpriv/drone-gogs pull: if-not-exists From 6364a6f841b71b7056cd674e031fa9976df336d0 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Thu, 16 Feb 2023 14:07:04 -0800 Subject: [PATCH 3/3] Update Goldens --- test/textfield_form_final.png | Bin 6024 -> 6016 bytes test/textfield_form_init.png | Bin 5180 -> 5171 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/test/textfield_form_final.png b/test/textfield_form_final.png index 03c23e2c37cceedb2dd364fb4cf8116f0793bbb1..64d499ab8ac87dba176d4f4d135c803185311ce8 100644 GIT binary patch delta 4985 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 Ugl4iI)LOvmoSj)Q+T-5;0I}9%egFUf diff --git a/test/textfield_form_init.png b/test/textfield_form_init.png index facd8e5e8974aca13051a477490a4da0efa6cdb7..d3f7d9806451b31a868f8b2f0895a958db91f44a 100644 GIT binary patch literal 5171 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 literal 5180 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