Merge pull request 'Upgrade libCwtch + Formatting Pass' (#82) from fix-reconnect into trunk

Reviewed-on: cwtch.im/cwtch-ui#82
Reviewed-by: erinn <erinn@openprivacy.ca>
This commit is contained in:
erinn 2021-06-30 14:18:50 -07:00
commit 1a8d91548e
15 changed files with 187 additions and 177 deletions

View File

@ -1 +1 @@
v1.0.0-12-g2e0b6ef-2021-06-29-23-42 v1.0.0-20-gf8eedca-2021-06-30-20-48

View File

@ -115,6 +115,5 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.'''); OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''');
yield LicenseEntryWithLineBreaks(["flaticons"], "Icons made by Freepik (https://www.freepik.com) from Flaticon (www.flaticon.com)"); yield LicenseEntryWithLineBreaks(["flaticons"], "Icons made by Freepik (https://www.freepik.com) from Flaticon (www.flaticon.com)");
} }

View File

@ -190,7 +190,8 @@ class FlwtchState extends State<Flwtch> {
}, },
), ),
); );
} else { //dual pane } else {
//dual pane
Provider.of<AppState>(navKey.currentContext!, listen: false).selectedProfile = args["ProfileOnion"]; Provider.of<AppState>(navKey.currentContext!, listen: false).selectedProfile = args["ProfileOnion"];
Provider.of<AppState>(navKey.currentContext!, listen: false).selectedConversation = args["Handle"]; Provider.of<AppState>(navKey.currentContext!, listen: false).selectedConversation = args["Handle"];
} }

View File

@ -22,10 +22,7 @@ class LinuxNotificationsManager implements NotificationsManager {
} }
Future<void> notify(String message) async { Future<void> notify(String message) async {
var iconPath = Uri.file(path.join(path.current, "cwtch.png")); var iconPath = Uri.file(path.join(path.current, "cwtch.png"));
client.notify(message, appName: "cwtch", client.notify(message, appName: "cwtch", appIcon: iconPath.toString(), replacesId: this.previous_id).then((Notification value) => previous_id = value.id);
appIcon: iconPath.toString(),
replacesId: this.previous_id).then((Notification value) =>
previous_id = value.id);
} }
} }
@ -40,4 +37,4 @@ NotificationsManager newDesktopNotificationsManager() {
print("Attempted to access DBUS for notifications but failed. Switching off notifications."); print("Attempted to access DBUS for notifications but failed. Switching off notifications.");
} }
return NullNotificationsManager(); return NullNotificationsManager();
} }

View File

@ -314,7 +314,6 @@ abstract class OpaqueThemeType {
double contactOnionTextSize() { double contactOnionTextSize() {
return 18; return 18;
} }
} }
class OpaqueDark extends OpaqueThemeType { class OpaqueDark extends OpaqueThemeType {
@ -1440,4 +1439,4 @@ class Opaque extends OpaqueThemeType {
} }
} }
*/ */

View File

@ -161,26 +161,40 @@ class Settings extends ChangeNotifier {
List<int> uiColumns(bool isLandscape) { List<int> uiColumns(bool isLandscape) {
var m = (!isLandscape || uiColumnModeLandscape == DualpaneMode.CopyPortrait) ? uiColumnModePortrait : uiColumnModeLandscape; var m = (!isLandscape || uiColumnModeLandscape == DualpaneMode.CopyPortrait) ? uiColumnModePortrait : uiColumnModeLandscape;
switch(m) { switch (m) {
case DualpaneMode.Single: return [1]; case DualpaneMode.Single:
case DualpaneMode.Dual1to2: return [1, 2]; return [1];
case DualpaneMode.Dual1to4: return [1, 4]; case DualpaneMode.Dual1to2:
return [1, 2];
case DualpaneMode.Dual1to4:
return [1, 4];
} }
print("impossible column configuration: portrait/$uiColumnModePortrait landscape/$uiColumnModeLandscape"); print("impossible column configuration: portrait/$uiColumnModePortrait landscape/$uiColumnModeLandscape");
return [1]; return [1];
} }
static List<DualpaneMode> uiColumnModeOptions(bool isLandscape) { static List<DualpaneMode> uiColumnModeOptions(bool isLandscape) {
if (isLandscape) return [DualpaneMode.CopyPortrait, DualpaneMode.Single, DualpaneMode.Dual1to2, DualpaneMode.Dual1to4,]; if (isLandscape)
else return [DualpaneMode.Single, DualpaneMode.Dual1to2, DualpaneMode.Dual1to4]; return [
DualpaneMode.CopyPortrait,
DualpaneMode.Single,
DualpaneMode.Dual1to2,
DualpaneMode.Dual1to4,
];
else
return [DualpaneMode.Single, DualpaneMode.Dual1to2, DualpaneMode.Dual1to4];
} }
static DualpaneMode uiColumnModeFromString(String m) { static DualpaneMode uiColumnModeFromString(String m) {
switch(m) { switch (m) {
case "DualpaneMode.Single": return DualpaneMode.Single; case "DualpaneMode.Single":
case "DualpaneMode.Dual1to2": return DualpaneMode.Dual1to2; return DualpaneMode.Single;
case "DualpaneMode.Dual1to4": return DualpaneMode.Dual1to4; case "DualpaneMode.Dual1to2":
case "DualpaneMode.CopyPortrait": return DualpaneMode.CopyPortrait; return DualpaneMode.Dual1to2;
case "DualpaneMode.Dual1to4":
return DualpaneMode.Dual1to4;
case "DualpaneMode.CopyPortrait":
return DualpaneMode.CopyPortrait;
} }
print("Error: ui requested translation of column mode [$m] which doesn't exist"); print("Error: ui requested translation of column mode [$m] which doesn't exist");
return DualpaneMode.Single; return DualpaneMode.Single;
@ -188,11 +202,15 @@ class Settings extends ChangeNotifier {
static String uiColumnModeToString(DualpaneMode m) { static String uiColumnModeToString(DualpaneMode m) {
// todo: translate // todo: translate
switch(m) { switch (m) {
case DualpaneMode.Single: return "Single"; case DualpaneMode.Single:
case DualpaneMode.Dual1to2: return "Double (1:2)"; return "Single";
case DualpaneMode.Dual1to4: return "Double (1:4)"; case DualpaneMode.Dual1to2:
case DualpaneMode.CopyPortrait: return "Same as portrait mode setting"; return "Double (1:2)";
case DualpaneMode.Dual1to4:
return "Double (1:4)";
case DualpaneMode.CopyPortrait:
return "Same as portrait mode setting";
} }
} }

View File

@ -166,7 +166,10 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
autoFillHints: [AutofillHints.newPassword], autoFillHints: [AutofillHints.newPassword],
validator: (value) { validator: (value) {
// Password field can be empty when just updating the profile, not on creation // Password field can be empty when just updating the profile, not on creation
if (Provider.of<ProfileInfoState>(context).isEncrypted && Provider.of<ProfileInfoState>(context, listen: false).onion.isEmpty && value.isEmpty && usePassword) { if (Provider.of<ProfileInfoState>(context).isEncrypted &&
Provider.of<ProfileInfoState>(context, listen: false).onion.isEmpty &&
value.isEmpty &&
usePassword) {
return AppLocalizations.of(context)!.passwordErrorEmpty; return AppLocalizations.of(context)!.passwordErrorEmpty;
} }
if (Provider.of<ErrorHandler>(context).deleteProfileError == true) { if (Provider.of<ErrorHandler>(context).deleteProfileError == true) {

View File

@ -29,7 +29,7 @@ class _DoubleColumnViewState extends State<DoubleColumnView> {
Flexible( Flexible(
flex: cols[1], flex: cols[1],
child: flwtch.selectedConversation == null child: flwtch.selectedConversation == null
? Card(child:Center(child: Text(AppLocalizations.of(context)!.addContactFirst))) ? Card(child: Center(child: Text(AppLocalizations.of(context)!.addContactFirst)))
: //dev : //dev
MultiProvider(providers: [ MultiProvider(providers: [
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context)), ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context)),

View File

@ -169,7 +169,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
)), )),
AboutListTile( AboutListTile(
icon: Icon(Icons.info, color: settings.current().mainTextColor()), icon: Icon(Icons.info, color: settings.current().mainTextColor()),
applicationIcon: Padding(padding:EdgeInsets.all(5), child: Icon(CwtchIcons.cwtch_knott)), applicationIcon: Padding(padding: EdgeInsets.all(5), child: Icon(CwtchIcons.cwtch_knott)),
applicationName: "Cwtch (Flutter UI)", applicationName: "Cwtch (Flutter UI)",
applicationVersion: AppLocalizations.of(context)!.versionBuilddate.replaceAll("%1", EnvironmentConfig.BUILD_VER).replaceAll("%2", EnvironmentConfig.BUILD_DATE), applicationVersion: AppLocalizations.of(context)!.versionBuilddate.replaceAll("%1", EnvironmentConfig.BUILD_VER).replaceAll("%2", EnvironmentConfig.BUILD_DATE),
applicationLegalese: '\u{a9} 2021 Open Privacy Research Society', applicationLegalese: '\u{a9} 2021 Open Privacy Research Society',

View File

@ -50,17 +50,19 @@ class _MessageViewState extends State<MessageView> {
appBar: AppBar( appBar: AppBar(
// setting leading to null makes it do the default behaviour; container() hides it // setting leading to null makes it do the default behaviour; container() hides it
leading: Provider.of<Settings>(context).uiColumns(appState.isLandscape(context)).length > 1 ? Container() : null, leading: Provider.of<Settings>(context).uiColumns(appState.isLandscape(context)).length > 1 ? Container() : null,
title: Row(children: [ title: Row(children: [
ProfileImage( ProfileImage(
imagePath: Provider.of<ContactInfoState>(context).imagePath, imagePath: Provider.of<ContactInfoState>(context).imagePath,
diameter: 42, diameter: 42,
border: Provider.of<Settings>(context).current().portraitOnlineBorderColor(), border: Provider.of<Settings>(context).current().portraitOnlineBorderColor(),
badgeTextColor: Colors.red, badgeTextColor: Colors.red,
badgeColor: Colors.red, badgeColor: Colors.red,
), ),
SizedBox( SizedBox(
width: 10, width: 10,
),Text(Provider.of<ContactInfoState>(context).nickname)]), ),
Text(Provider.of<ContactInfoState>(context).nickname)
]),
actions: [ actions: [
//IconButton(icon: Icon(Icons.chat), onPressed: _pushContactSettings), //IconButton(icon: Icon(Icons.chat), onPressed: _pushContactSettings),
//IconButton(icon: Icon(Icons.list), onPressed: _pushContactSettings), //IconButton(icon: Icon(Icons.list), onPressed: _pushContactSettings),

View File

@ -40,45 +40,41 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
// Prevents Android back button from closing the app on the profile manager screen // Prevents Android back button from closing the app on the profile manager screen
// (which would shutdown connections and all kinds of other expensive to generate things) // (which would shutdown connections and all kinds of other expensive to generate things)
// TODO pop up a dialogue regarding closing the app? // TODO pop up a dialogue regarding closing the app?
builder: (context, settings, child) => builder: (context, settings, child) => WillPopScope(
WillPopScope( onWillPop: () async {
onWillPop: () async { _modalShutdown();
_modalShutdown(); return Provider.of<AppState>(context, listen: false).cwtchIsClosing;
return Provider.of<AppState>(context, listen: false).cwtchIsClosing; },
}, child: Scaffold(
child: Scaffold( backgroundColor: settings.theme.backgroundMainColor(),
backgroundColor: settings.theme.backgroundMainColor(), appBar: AppBar(
appBar: AppBar( title: Row(children: [
title: Row(children: [ Image(
Image( image: AssetImage("assets/core/knott-white.png"),
image: AssetImage("assets/core/knott-white.png"), filterQuality: FilterQuality.medium,
filterQuality: FilterQuality.medium, isAntiAlias: true,
isAntiAlias: true, width: 32,
width: 32, height: 32,
height: 32, colorBlendMode: BlendMode.dstIn,
colorBlendMode: BlendMode.dstIn, color: Provider.of<Settings>(context).theme.backgroundHilightElementColor(),
color: Provider
.of<Settings>(context)
.theme
.backgroundHilightElementColor(),
),
SizedBox(
width: 10,
),
Expanded(child: Text(AppLocalizations.of(context)!.titleManageProfiles, style: TextStyle(color: settings.current().mainTextColor())))
]),
actions: getActions(),
), ),
floatingActionButton: FloatingActionButton( SizedBox(
onPressed: _pushAddEditProfile, width: 10,
tooltip: AppLocalizations.of(context)!.addNewProfileBtn,
child: Icon(
Icons.add,
semanticLabel: AppLocalizations.of(context)!.addNewProfileBtn,
),
), ),
body: _buildProfileManager(), Expanded(child: Text(AppLocalizations.of(context)!.titleManageProfiles, style: TextStyle(color: settings.current().mainTextColor())))
)), ]),
actions: getActions(),
),
floatingActionButton: FloatingActionButton(
onPressed: _pushAddEditProfile,
tooltip: AppLocalizations.of(context)!.addNewProfileBtn,
child: Icon(
Icons.add,
semanticLabel: AppLocalizations.of(context)!.addNewProfileBtn,
),
),
body: _buildProfileManager(),
)),
); );
} }

View File

@ -33,7 +33,11 @@ class _ContactRowState extends State<ContactRow> {
diameter: 64.0, diameter: 64.0,
imagePath: contact.imagePath, imagePath: contact.imagePath,
maskOut: !contact.isOnline(), maskOut: !contact.isOnline(),
border: contact.isOnline() ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : contact.isBlocked ? Provider.of<Settings>(context).theme.portraitBlockedBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()), border: contact.isOnline()
? Provider.of<Settings>(context).theme.portraitOnlineBorderColor()
: contact.isBlocked
? Provider.of<Settings>(context).theme.portraitBlockedBorderColor()
: Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
), ),
Expanded( Expanded(
child: Padding( child: Padding(
@ -44,13 +48,16 @@ class _ContactRowState extends State<ContactRow> {
Text( 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(fontSize: Provider.of<Settings>(context).theme.contactOnionTextSize(), style: TextStyle(
color: contact.isBlocked ? Provider.of<Settings>(context).theme.portraitBlockedTextColor() : Provider.of<Settings>(context).theme.mainTextColor()), //Provider.of<FlwtchState>(context).biggerFont, fontSize: Provider.of<Settings>(context).theme.contactOnionTextSize(),
color: contact.isBlocked
? Provider.of<Settings>(context).theme.portraitBlockedTextColor()
: Provider.of<Settings>(context).theme.mainTextColor()), //Provider.of<FlwtchState>(context).biggerFont,
softWrap: true, softWrap: true,
overflow: TextOverflow.visible, overflow: TextOverflow.visible,
), ),
Text(contact.onion, Text(contact.onion,
style: TextStyle(color: contact.isBlocked ? Provider.of<Settings>(context).theme.portraitBlockedTextColor() : Provider.of<Settings>(context).theme.mainTextColor())), style: TextStyle(color: contact.isBlocked ? Provider.of<Settings>(context).theme.portraitBlockedTextColor() : Provider.of<Settings>(context).theme.mainTextColor())),
], ],
))), ))),
Padding( Padding(
@ -60,7 +67,10 @@ class _ContactRowState extends State<ContactRow> {
IconButton( IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
iconSize: 16, iconSize: 16,
icon: Icon(Icons.favorite, color: Provider.of<Settings>(context).theme.mainTextColor(),), icon: Icon(
Icons.favorite,
color: Provider.of<Settings>(context).theme.mainTextColor(),
),
tooltip: AppLocalizations.of(context)!.tooltipAcceptContactRequest, tooltip: AppLocalizations.of(context)!.tooltipAcceptContactRequest,
onPressed: _btnApprove, onPressed: _btnApprove,
), ),

View File

@ -66,18 +66,18 @@ class InvitationBubbleState extends State<InvitationBubble> {
return MalformedBubble(); return MalformedBubble();
} }
var wdgMessage = isGroup && !showGroupInvite ? var wdgMessage = isGroup && !showGroupInvite
Text(AppLocalizations.of(context)!.groupInviteSettingsWarning) : ? Text(AppLocalizations.of(context)!.groupInviteSettingsWarning)
fromMe : fromMe
? senderInviteChrome(AppLocalizations.of(context)!.sendAnInvitation, ? senderInviteChrome(AppLocalizations.of(context)!.sendAnInvitation,
isGroup ? Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageState>(context).inviteTarget)!.nickname : Provider.of<MessageState>(context).message, myKey) isGroup ? Provider.of<ProfileInfoState>(context).contactList.getContact(Provider.of<MessageState>(context).inviteTarget)!.nickname : Provider.of<MessageState>(context).message, myKey)
: (inviteChrome(isGroup ? AppLocalizations.of(context)!.inviteToGroup : AppLocalizations.of(context)!.contactSuggestion, Provider.of<MessageState>(context).inviteNick, : (inviteChrome(isGroup ? AppLocalizations.of(context)!.inviteToGroup : AppLocalizations.of(context)!.contactSuggestion, Provider.of<MessageState>(context).inviteNick,
Provider.of<MessageState>(context).inviteTarget, myKey)); Provider.of<MessageState>(context).inviteTarget, myKey));
Widget wdgDecorations; Widget wdgDecorations;
if (isGroup && !showGroupInvite) { if (isGroup && !showGroupInvite) {
wdgDecorations = Text('\u202F'); wdgDecorations = Text('\u202F');
} else if (fromMe) { } else if (fromMe) {
wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageState>(context).ackd, errored: Provider.of<MessageState>(context).error, fromMe: fromMe, prettyDate: prettyDate); wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageState>(context).ackd, errored: Provider.of<MessageState>(context).error, fromMe: fromMe, prettyDate: prettyDate);
} else if (isAccepted) { } else if (isAccepted) {
wdgDecorations = Text(AppLocalizations.of(context)!.accepted + '\u202F'); wdgDecorations = Text(AppLocalizations.of(context)!.accepted + '\u202F');
@ -113,7 +113,8 @@ class InvitationBubbleState extends State<InvitationBubble> {
child: Padding( child: Padding(
padding: EdgeInsets.all(9.0), padding: EdgeInsets.all(9.0),
child: Wrap(runAlignment: WrapAlignment.spaceEvenly, alignment: WrapAlignment.spaceEvenly, runSpacing: 1.0, crossAxisAlignment: WrapCrossAlignment.center, children: [ child: Wrap(runAlignment: WrapAlignment.spaceEvenly, alignment: WrapAlignment.spaceEvenly, runSpacing: 1.0, crossAxisAlignment: WrapCrossAlignment.center, children: [
Center(widthFactor: 1, child: Padding(padding: EdgeInsets.all(10.0), child: Icon(isGroup && !showGroupInvite ? CwtchIcons.enable_experiments : CwtchIcons.send_invite, size: 32))), Center(
widthFactor: 1, child: Padding(padding: EdgeInsets.all(10.0), child: Icon(isGroup && !showGroupInvite ? CwtchIcons.enable_experiments : CwtchIcons.send_invite, size: 32))),
Center( Center(
widthFactor: 1.0, widthFactor: 1.0,
child: Column( child: Column(

View File

@ -16,11 +16,10 @@ class _MessageListState extends State<MessageList> {
@override @override
Widget build(BuildContext outerContext) { Widget build(BuildContext outerContext) {
bool isP2P = !Provider.of<ContactInfoState>(context).isGroup;
bool isP2P = !Provider.of<ContactInfoState>(context).isGroup;
bool isGroupAndSyncing = Provider.of<ContactInfoState>(context).isGroup == true && Provider.of<ContactInfoState>(context).status == "Authenticated"; bool isGroupAndSyncing = Provider.of<ContactInfoState>(context).isGroup == true && Provider.of<ContactInfoState>(context).status == "Authenticated";
bool isGroupAndSynced = Provider.of<ContactInfoState>(context).isGroup && Provider.of<ContactInfoState>(context).status == "Synced"; bool isGroupAndSynced = Provider.of<ContactInfoState>(context).isGroup && Provider.of<ContactInfoState>(context).status == "Synced";
bool isGroupAndNotAuthenticated= Provider.of<ContactInfoState>(context).isGroup && Provider.of<ContactInfoState>(context).status != "Authenticated"; bool isGroupAndNotAuthenticated = Provider.of<ContactInfoState>(context).isGroup && Provider.of<ContactInfoState>(context).status != "Authenticated";
bool showEphemeralWarning = (isP2P && Provider.of<ContactInfoState>(context).savePeerHistory != "SaveHistory"); bool showEphemeralWarning = (isP2P && Provider.of<ContactInfoState>(context).savePeerHistory != "SaveHistory");
bool showOfflineWarning = Provider.of<ContactInfoState>(context).isOnline() == false; bool showOfflineWarning = Provider.of<ContactInfoState>(context).isOnline() == false;
@ -37,18 +36,17 @@ class _MessageListState extends State<MessageList> {
child: Container( child: Container(
padding: EdgeInsets.all(5.0), padding: EdgeInsets.all(5.0),
color: Provider.of<Settings>(context).theme.defaultButtonActiveColor(), color: Provider.of<Settings>(context).theme.defaultButtonActiveColor(),
child: showSyncing ? child: showSyncing
Text(AppLocalizations.of(context)!.serverNotSynced, ? Text(AppLocalizations.of(context)!.serverNotSynced, textAlign: TextAlign.center)
textAlign: TextAlign.center) : showOfflineWarning
: showOfflineWarning ? Text(Provider.of<ContactInfoState>(context).isGroup ? AppLocalizations.of(context)!.serverConnectivityDisconnected : AppLocalizations.of(context)!.peerOfflineMessage,
? Text(Provider.of<ContactInfoState>(context).isGroup ? AppLocalizations.of(context)!.serverConnectivityDisconnected : AppLocalizations.of(context)!.peerOfflineMessage, textAlign: TextAlign.center)
textAlign: TextAlign.center) // Only show the ephemeral status for peer conversations, not for groups...
// Only show the ephemeral status for peer conversations, not for groups... : (showEphemeralWarning
: (showEphemeralWarning ? Text(AppLocalizations.of(context)!.chatHistoryDefault, textAlign: TextAlign.center)
? Text(AppLocalizations.of(context)!.chatHistoryDefault, textAlign: TextAlign.center) :
: // We are not allowed to put null here, so put an empty text widge
// We are not allowed to put null here, so put an empty text widge Text("")),
Text("")),
)), )),
Expanded( Expanded(
child: Scrollbar( child: Scrollbar(
@ -63,30 +61,32 @@ class _MessageListState extends State<MessageList> {
alignment: Alignment.center, alignment: Alignment.center,
image: AssetImage("assets/core/negative_heart_512px.png"), image: AssetImage("assets/core/negative_heart_512px.png"),
colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.hilightElementTextColor(), BlendMode.srcIn))), colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.hilightElementTextColor(), BlendMode.srcIn))),
// Don't load messages for syncing server... // Don't load messages for syncing server...
child: loadMessages ? ListView.builder( child: loadMessages
controller: ctrlr1, ? ListView.builder(
itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages, controller: ctrlr1,
reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction... itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages,
itemBuilder: (itemBuilderContext, index) { reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction...
var trueIndex = Provider.of<ContactInfoState>(outerContext).totalMessages - index - 1; itemBuilder: (itemBuilderContext, index) {
return ChangeNotifierProvider( var trueIndex = Provider.of<ContactInfoState>(outerContext).totalMessages - index - 1;
key: ValueKey(trueIndex), return ChangeNotifierProvider(
create: (x) => MessageState( key: ValueKey(trueIndex),
context: itemBuilderContext, create: (x) => MessageState(
profileOnion: Provider.of<ProfileInfoState>(outerContext, listen: false).onion, context: itemBuilderContext,
// We don't want to listen for updates to the contact handle... profileOnion: Provider.of<ProfileInfoState>(outerContext, listen: false).onion,
contactHandle: Provider.of<ContactInfoState>(x, listen: false).onion, // We don't want to listen for updates to the contact handle...
messageIndex: trueIndex, contactHandle: Provider.of<ContactInfoState>(x, listen: false).onion,
), messageIndex: trueIndex,
builder: (bcontext, child) { ),
String idx = Provider.of<ContactInfoState>(outerContext).isGroup == true && Provider.of<MessageState>(bcontext).signature.isEmpty == false builder: (bcontext, child) {
? Provider.of<MessageState>(bcontext).signature String idx = Provider.of<ContactInfoState>(outerContext).isGroup == true && Provider.of<MessageState>(bcontext).signature.isEmpty == false
: trueIndex.toString(); ? Provider.of<MessageState>(bcontext).signature
return RepaintBoundary(child: MessageRow(key: Provider.of<ContactInfoState>(bcontext).getMessageKey(idx))); : trueIndex.toString();
}); return RepaintBoundary(child: MessageRow(key: Provider.of<ContactInfoState>(bcontext).getMessageKey(idx)));
}, });
) : null ))) },
)
: null)))
]))); ])));
} }
} }

View File

@ -30,43 +30,29 @@ class _ProfileRowState extends State<ProfileRow> {
padding: const EdgeInsets.all(2.0), //border size padding: const EdgeInsets.all(2.0), //border size
child: ProfileImage( child: ProfileImage(
badgeCount: 0, badgeCount: 0,
badgeColor: Provider badgeColor: Provider.of<Settings>(context).theme.portraitProfileBadgeColor(),
.of<Settings>(context) badgeTextColor: Provider.of<Settings>(context).theme.portraitProfileBadgeTextColor(),
.theme
.portraitProfileBadgeColor(),
badgeTextColor: Provider
.of<Settings>(context)
.theme
.portraitProfileBadgeTextColor(),
diameter: 64.0, diameter: 64.0,
imagePath: profile.imagePath, imagePath: profile.imagePath,
border: profile.isOnline ? Provider border: profile.isOnline ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor())),
.of<Settings>(context)
.theme
.portraitOnlineBorderColor() : Provider
.of<Settings>(context)
.theme
.portraitOfflineBorderColor())),
Expanded( Expanded(
child: Column( child: Column(
children: [ children: [
Text( Text(
profile.nickname, profile.nickname,
semanticsLabel: profile.nickname, semanticsLabel: profile.nickname,
style: Provider style: Provider.of<FlwtchState>(context).biggerFont,
.of<FlwtchState>(context) softWrap: true,
.biggerFont, overflow: TextOverflow.ellipsis,
softWrap: true, ),
overflow: TextOverflow.ellipsis, ExcludeSemantics(
), child: Text(
ExcludeSemantics( profile.onion,
child: Text( softWrap: true,
profile.onion, overflow: TextOverflow.ellipsis,
softWrap: true, ))
overflow: TextOverflow.ellipsis, ],
)) )),
],
)),
IconButton( IconButton(
enableFeedback: true, enableFeedback: true,
tooltip: AppLocalizations.of(context)!.editProfile + " " + profile.nickname, tooltip: AppLocalizations.of(context)!.editProfile + " " + profile.nickname,
@ -83,7 +69,7 @@ class _ProfileRowState extends State<ProfileRow> {
appState.selectedProfile = profile.onion; appState.selectedProfile = profile.onion;
appState.selectedConversation = null; appState.selectedConversation = null;
_pushContactList(profile, appState.isLandscape(context));//orientation == Orientation.landscape); _pushContactList(profile, appState.isLandscape(context)); //orientation == Orientation.landscape);
}); });
}, },
)); ));
@ -94,19 +80,17 @@ class _ProfileRowState extends State<ProfileRow> {
MaterialPageRoute<void>( MaterialPageRoute<void>(
settings: RouteSettings(name: "conversations"), settings: RouteSettings(name: "conversations"),
builder: (BuildContext buildcontext) { builder: (BuildContext buildcontext) {
return OrientationBuilder( return OrientationBuilder(builder: (orientationBuilderContext, orientation) {
builder: (orientationBuilderContext, orientation) { return MultiProvider(
return MultiProvider( providers: [
providers: [ ChangeNotifierProvider<ProfileInfoState>.value(value: profile),
ChangeNotifierProvider<ProfileInfoState>.value(value: profile), ChangeNotifierProvider<ContactListState>.value(value: profile.contactList),
ChangeNotifierProvider<ContactListState>.value(value: profile.contactList), ],
], builder: (innercontext, widget) {
builder: (innercontext, widget) { var appState = Provider.of<AppState>(context);
var appState = Provider.of<AppState>(context); var settings = Provider.of<Settings>(context);
var settings = Provider.of<Settings>(context); return settings.uiColumns(appState.isLandscape(innercontext)).length > 1 ? DoubleColumnView() : ContactsView();
return settings.uiColumns(appState.isLandscape(innercontext)).length > 1 ? DoubleColumnView() : ContactsView(); });
}
);
}); });
}, },
), ),