Fixing Duplicate Key Issues + FileBubble SetState Builder Issues
This commit is contained in:
parent
51fae2e7ef
commit
a4cb5051b5
|
@ -282,8 +282,6 @@ class ProfileInfoState extends ChangeNotifier {
|
||||||
this._contacts.updateLastMessageTime(this._contacts._contacts.first.identifier, this._contacts._contacts.first.lastMessageTime);
|
this._contacts.updateLastMessageTime(this._contacts._contacts.first.identifier, this._contacts._contacts.first.lastMessageTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse out the server list json into our server info state struct...
|
// Parse out the server list json into our server info state struct...
|
||||||
|
|
|
@ -58,11 +58,15 @@ Message compileOverlay(MessageMetadata metadata, String messageData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Message> messageHandler(BuildContext context, String profileOnion, int conversationIdentifier, int index, {bool byID = false}) {
|
Future<Message> messageHandler(BuildContext context, String profileOnion, int conversationIdentifier, int index, {bool byID = false}) {
|
||||||
var cache = Provider.of<ProfileInfoState>(context).contactList.getContact(conversationIdentifier)?.messageCache;
|
try {
|
||||||
if (cache != null && cache.length > index) {
|
var cache = Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(conversationIdentifier)?.messageCache;
|
||||||
if (cache[index] != null) {
|
if (cache != null && cache.length > index) {
|
||||||
return Future.value(compileOverlay(cache[index]!.metadata, cache[index]!.wrapper));
|
if (cache[index] != null) {
|
||||||
|
return Future.value(compileOverlay(cache[index]!.metadata, cache[index]!.wrapper));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// provider check failed...make an expensive call...
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -19,7 +19,6 @@ class FileMessage extends Message {
|
||||||
@override
|
@override
|
||||||
Widget getWidget(BuildContext context, Key key) {
|
Widget getWidget(BuildContext context, Key key) {
|
||||||
return ChangeNotifierProvider.value(
|
return ChangeNotifierProvider.value(
|
||||||
key: key,
|
|
||||||
value: this.metadata,
|
value: this.metadata,
|
||||||
builder: (bcontext, child) {
|
builder: (bcontext, child) {
|
||||||
dynamic shareObj = jsonDecode(this.content);
|
dynamic shareObj = jsonDecode(this.content);
|
||||||
|
|
|
@ -19,7 +19,6 @@ class InviteMessage extends Message {
|
||||||
@override
|
@override
|
||||||
Widget getWidget(BuildContext context, Key key) {
|
Widget getWidget(BuildContext context, Key key) {
|
||||||
return ChangeNotifierProvider.value(
|
return ChangeNotifierProvider.value(
|
||||||
key: key,
|
|
||||||
value: this.metadata,
|
value: this.metadata,
|
||||||
builder: (bcontext, child) {
|
builder: (bcontext, child) {
|
||||||
String inviteTarget;
|
String inviteTarget;
|
||||||
|
@ -37,7 +36,7 @@ class InviteMessage extends Message {
|
||||||
inviteTarget = jsonObj['GroupID'];
|
inviteTarget = jsonObj['GroupID'];
|
||||||
inviteNick = jsonObj['GroupName'];
|
inviteNick = jsonObj['GroupName'];
|
||||||
} else {
|
} else {
|
||||||
return MessageRow(MalformedBubble(), key: key);
|
return MessageRow(MalformedBubble());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite), key: key);
|
return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite), key: key);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||||
|
|
||||||
import 'package:cwtch/models/message.dart';
|
import 'package:cwtch/models/message.dart';
|
||||||
import 'package:cwtch/models/messages/malformedmessage.dart';
|
import 'package:cwtch/models/messages/malformedmessage.dart';
|
||||||
|
import 'package:cwtch/widgets/malformedbubble.dart';
|
||||||
import 'package:cwtch/widgets/messagerow.dart';
|
import 'package:cwtch/widgets/messagerow.dart';
|
||||||
import 'package:cwtch/widgets/quotedmessage.dart';
|
import 'package:cwtch/widgets/quotedmessage.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
@ -51,7 +52,7 @@ class QuotedMessage extends Message {
|
||||||
dynamic message = jsonDecode(this.content);
|
dynamic message = jsonDecode(this.content);
|
||||||
return Text(message["body"]);
|
return Text(message["body"]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return MalformedMessage(this.metadata).getWidget(context, Key("malformed"));
|
return MalformedBubble();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -67,7 +68,7 @@ class QuotedMessage extends Message {
|
||||||
dynamic message = jsonDecode(this.content);
|
dynamic message = jsonDecode(this.content);
|
||||||
|
|
||||||
if (message["body"] == null || message["quotedHash"] == null) {
|
if (message["body"] == null || message["quotedHash"] == null) {
|
||||||
return MalformedMessage(this.metadata).getWidget(context, key);
|
return MalformedBubble();
|
||||||
}
|
}
|
||||||
|
|
||||||
var quotedMessagePotentials = Provider.of<FlwtchState>(context).cwtch.GetMessageByContentHash(metadata.profileOnion, metadata.conversationIdentifier, message["quotedHash"]);
|
var quotedMessagePotentials = Provider.of<FlwtchState>(context).cwtch.GetMessageByContentHash(metadata.profileOnion, metadata.conversationIdentifier, message["quotedHash"]);
|
||||||
|
@ -94,14 +95,14 @@ class QuotedMessage extends Message {
|
||||||
return MessageRow(
|
return MessageRow(
|
||||||
QuotedMessageBubble(message["body"], quotedMessage.then((LocallyIndexedMessage? localIndex) {
|
QuotedMessageBubble(message["body"], quotedMessage.then((LocallyIndexedMessage? localIndex) {
|
||||||
if (localIndex != null) {
|
if (localIndex != null) {
|
||||||
return messageHandler(context, metadata.profileOnion, metadata.conversationIdentifier, localIndex.index);
|
return messageHandler(bcontext, metadata.profileOnion, metadata.conversationIdentifier, localIndex.index);
|
||||||
}
|
}
|
||||||
return MalformedMessage(this.metadata);
|
return MalformedMessage(this.metadata);
|
||||||
})),
|
})),
|
||||||
key: key);
|
key: key);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return MalformedMessage(this.metadata).getWidget(context, key);
|
return MalformedBubble();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ class ProfileServerListState extends ChangeNotifier {
|
||||||
// online v offline
|
// online v offline
|
||||||
if (a.status == "Synced" && b.status != "Synced") {
|
if (a.status == "Synced" && b.status != "Synced") {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (a.status != "Synced" && b.status == "Synced") {
|
} else if (a.status != "Synced" && b.status == "Synced") {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ class RemoteServerInfoState extends ChangeNotifier {
|
||||||
List<ContactInfoState> _groups = [];
|
List<ContactInfoState> _groups = [];
|
||||||
|
|
||||||
RemoteServerInfoState({required this.onion, required this.identifier, required this.description, required this.status});
|
RemoteServerInfoState({required this.onion, required this.identifier, required this.description, required this.status});
|
||||||
|
|
||||||
void updateDescription(String newDescription) {
|
void updateDescription(String newDescription) {
|
||||||
this.description = newDescription;
|
this.description = newDescription;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
|
@ -107,7 +107,7 @@ class _AddEditProfileViewState extends State<AddEditProfileView> {
|
||||||
labelText: AppLocalizations.of(context)!.yourDisplayName,
|
labelText: AppLocalizations.of(context)!.yourDisplayName,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value.isEmpty) {
|
if (value.isEmpty) {
|
||||||
return AppLocalizations.of(context)!.displayNameTooltip;
|
return AppLocalizations.of(context)!.displayNameTooltip;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
|
@ -117,7 +117,7 @@ class _ContactsViewState extends State<ContactsView> {
|
||||||
if (Provider.of<Settings>(context, listen: false).isExperimentEnabled(ServerManagementExperiment)) {
|
if (Provider.of<Settings>(context, listen: false).isExperimentEnabled(ServerManagementExperiment)) {
|
||||||
actions.add(IconButton(
|
actions.add(IconButton(
|
||||||
icon: Icon(CwtchIcons.dns_24px),
|
icon: Icon(CwtchIcons.dns_24px),
|
||||||
tooltip: AppLocalizations.of(context)!.manageKnownServersButton,
|
tooltip: AppLocalizations.of(context)!.manageKnownServersButton,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_pushServers();
|
_pushServers();
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -229,7 +229,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
||||||
),
|
),
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: settings.isExperimentEnabled(FileSharingExperiment),
|
visible: settings.isExperimentEnabled(FileSharingExperiment),
|
||||||
child: Column(children:[
|
child: Column(children: [
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
title: Text(AppLocalizations.of(context)!.settingImagePreviews, style: TextStyle(color: settings.current().mainTextColor())),
|
title: Text(AppLocalizations.of(context)!.settingImagePreviews, style: TextStyle(color: settings.current().mainTextColor())),
|
||||||
subtitle: Text(AppLocalizations.of(context)!.settingImagePreviewsDescription),
|
subtitle: Text(AppLocalizations.of(context)!.settingImagePreviewsDescription),
|
||||||
|
|
|
@ -10,14 +10,12 @@ import '../main.dart';
|
||||||
import '../model.dart';
|
import '../model.dart';
|
||||||
import '../settings.dart';
|
import '../settings.dart';
|
||||||
|
|
||||||
|
|
||||||
class ProfileServersView extends StatefulWidget {
|
class ProfileServersView extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_ProfileServersView createState() => _ProfileServersView();
|
_ProfileServersView createState() => _ProfileServersView();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ProfileServersView extends State<ProfileServersView> {
|
class _ProfileServersView extends State<ProfileServersView> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
|
@ -25,9 +23,10 @@ class _ProfileServersView extends State<ProfileServersView> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var knownServers = Provider.of<ProfileInfoState>(context).serverList.servers.map<String>((RemoteServerInfoState remoteServer) {
|
||||||
var knownServers = Provider.of<ProfileInfoState>(context).serverList.servers.map<String>((RemoteServerInfoState remoteServer) { return remoteServer.onion + ".onion"; }).toSet();
|
return remoteServer.onion + ".onion";
|
||||||
var importServerList = Provider.of<ServerListState>(context).servers.where((server) => !knownServers.contains(server.onion) ).map<DropdownMenuItem<String>>((ServerInfoState serverInfo) {
|
}).toSet();
|
||||||
|
var importServerList = Provider.of<ServerListState>(context).servers.where((server) => !knownServers.contains(server.onion)).map<DropdownMenuItem<String>>((ServerInfoState serverInfo) {
|
||||||
return DropdownMenuItem<String>(
|
return DropdownMenuItem<String>(
|
||||||
value: serverInfo.onion,
|
value: serverInfo.onion,
|
||||||
child: Text(
|
child: Text(
|
||||||
|
@ -37,25 +36,22 @@ class _ProfileServersView extends State<ProfileServersView> {
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
importServerList.insert(0, DropdownMenuItem<String>(
|
importServerList.insert(0, DropdownMenuItem<String>(value: "", child: Text(AppLocalizations.of(context)!.importLocalServerSelectText)));
|
||||||
value: "",
|
|
||||||
child: Text(AppLocalizations.of(context)!.importLocalServerSelectText)));
|
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(MediaQuery
|
title: Text(MediaQuery.of(context).size.width > 600 ? AppLocalizations.of(context)!.manageKnownServersLong : AppLocalizations.of(context)!.manageKnownServersShort),
|
||||||
.of(context)
|
|
||||||
.size
|
|
||||||
.width > 600 ? AppLocalizations.of(context)!.manageKnownServersLong : AppLocalizations.of(context)!.manageKnownServersShort),
|
|
||||||
),
|
),
|
||||||
body: Consumer<ProfileInfoState>(builder: (context, profile, child) {
|
body: Consumer<ProfileInfoState>(
|
||||||
|
builder: (context, profile, child) {
|
||||||
ProfileServerListState servers = profile.serverList;
|
ProfileServerListState servers = profile.serverList;
|
||||||
final tiles = servers.servers.map((RemoteServerInfoState server) {
|
final tiles = servers.servers.map(
|
||||||
return ChangeNotifierProvider<RemoteServerInfoState>.value(
|
(RemoteServerInfoState server) {
|
||||||
value: server,
|
return ChangeNotifierProvider<RemoteServerInfoState>.value(
|
||||||
builder: (context, child) => RepaintBoundary(child: RemoteServerRow()),
|
value: server,
|
||||||
);
|
builder: (context, child) => RepaintBoundary(child: RemoteServerRow()),
|
||||||
},
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
final divided = ListTile.divideTiles(
|
final divided = ListTile.divideTiles(
|
||||||
|
@ -63,37 +59,31 @@ class _ProfileServersView extends State<ProfileServersView> {
|
||||||
tiles: tiles,
|
tiles: tiles,
|
||||||
).toList();
|
).toList();
|
||||||
|
|
||||||
final importCard = Card( child: ListTile(
|
final importCard = Card(
|
||||||
title: Text(AppLocalizations.of(context)!.importLocalServerLabel),
|
child: ListTile(
|
||||||
leading: Icon(CwtchIcons.add_circle_24px , color: Provider.of<Settings>(context).current().mainTextColor()),
|
title: Text(AppLocalizations.of(context)!.importLocalServerLabel),
|
||||||
trailing: DropdownButton(
|
leading: Icon(CwtchIcons.add_circle_24px, color: Provider.of<Settings>(context).current().mainTextColor()),
|
||||||
onChanged: (String? importServer) {
|
trailing: DropdownButton(
|
||||||
if (importServer!.isNotEmpty) {
|
onChanged: (String? importServer) {
|
||||||
var server = Provider.of<ServerListState>(context).getServer(importServer)!;
|
if (importServer!.isNotEmpty) {
|
||||||
showImportConfirm(context, profile.onion, server.onion, server.description, server.serverBundle);
|
var server = Provider.of<ServerListState>(context).getServer(importServer)!;
|
||||||
}
|
showImportConfirm(context, profile.onion, server.onion, server.description, server.serverBundle);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
value: "",
|
value: "",
|
||||||
items: importServerList,
|
items: importServerList,
|
||||||
|
)));
|
||||||
)));
|
|
||||||
|
|
||||||
return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) {
|
return LayoutBuilder(builder: (BuildContext context, BoxConstraints viewportConstraints) {
|
||||||
return Scrollbar(
|
return Scrollbar(
|
||||||
isAlwaysShown: true,
|
isAlwaysShown: true,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child:
|
child: Container(
|
||||||
Container(
|
margin: EdgeInsets.fromLTRB(5, 0, 5, 10),
|
||||||
margin: EdgeInsets.fromLTRB(5, 0, 5, 10),
|
padding: EdgeInsets.fromLTRB(5, 0, 5, 10),
|
||||||
padding: EdgeInsets.fromLTRB(5, 0, 5, 10),
|
child: Column(children: [if (importServerList.length > 1) importCard, Column(children: divided)]))));
|
||||||
child: Column(children: [
|
});
|
||||||
|
|
||||||
if (importServerList.length > 1) importCard,
|
|
||||||
|
|
||||||
Column( children: divided )
|
|
||||||
]))));});
|
|
||||||
|
|
||||||
return ListView(children: divided);
|
return ListView(children: divided);
|
||||||
},
|
},
|
||||||
|
@ -102,7 +92,7 @@ class _ProfileServersView extends State<ProfileServersView> {
|
||||||
|
|
||||||
showImportConfirm(BuildContext context, String profileHandle, String serverHandle, String serverDesc, String bundle) {
|
showImportConfirm(BuildContext context, String profileHandle, String serverHandle, String serverDesc, String bundle) {
|
||||||
var serverLabel = serverDesc.isNotEmpty ? serverDesc : serverHandle;
|
var serverLabel = serverDesc.isNotEmpty ? serverDesc : serverHandle;
|
||||||
serverHandle = serverHandle.substring(0, serverHandle.length-6 ); // remove '.onion'
|
serverHandle = serverHandle.substring(0, serverHandle.length - 6); // remove '.onion'
|
||||||
// set up the buttons
|
// set up the buttons
|
||||||
Widget cancelButton = ElevatedButton(
|
Widget cancelButton = ElevatedButton(
|
||||||
child: Text(AppLocalizations.of(context)!.cancel),
|
child: Text(AppLocalizations.of(context)!.cancel),
|
||||||
|
@ -118,15 +108,9 @@ class _ProfileServersView extends State<ProfileServersView> {
|
||||||
Future.delayed(const Duration(milliseconds: 500), () {
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
var profile = Provider.of<ProfileInfoState>(context);
|
var profile = Provider.of<ProfileInfoState>(context);
|
||||||
if (profile.serverList.getServer(serverHandle) != null) {
|
if (profile.serverList.getServer(serverHandle) != null) {
|
||||||
profile.serverList.getServer(serverHandle)?.updateDescription(
|
profile.serverList.getServer(serverHandle)?.updateDescription(serverDesc);
|
||||||
serverDesc);
|
|
||||||
|
|
||||||
Provider
|
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profile.onion, profile.serverList.getServer(serverHandle)!.identifier, "server.description", serverDesc);
|
||||||
.of<FlwtchState>(context, listen: false)
|
|
||||||
.cwtch
|
|
||||||
.SetConversationAttribute(profile.onion, profile.serverList
|
|
||||||
.getServer(serverHandle)
|
|
||||||
!.identifier, "server.description", serverDesc);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
@ -149,7 +133,4 @@ class _ProfileServersView extends State<ProfileServersView> {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -50,63 +50,62 @@ class _RemoteServerViewState extends State<RemoteServerView> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer3<ProfileInfoState, RemoteServerInfoState, Settings>(builder: (context, profile, serverInfoState, settings, child) {
|
return Consumer3<ProfileInfoState, RemoteServerInfoState, Settings>(builder: (context, profile, serverInfoState, settings, child) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(title: Text(ctrlrDesc.text.isNotEmpty ? ctrlrDesc.text : serverInfoState.onion)),
|
||||||
title: Text(ctrlrDesc.text.isNotEmpty ? ctrlrDesc.text : serverInfoState.onion)
|
body: Container(
|
||||||
),
|
margin: EdgeInsets.fromLTRB(30, 0, 30, 10),
|
||||||
body: Container(
|
padding: EdgeInsets.fromLTRB(20, 0, 20, 10),
|
||||||
margin: EdgeInsets.fromLTRB(30, 0, 30, 10),
|
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
padding: EdgeInsets.fromLTRB(20, 0, 20, 10),
|
SizedBox(
|
||||||
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
height: 20,
|
||||||
SizedBox(
|
),
|
||||||
height: 20,
|
CwtchLabel(label: AppLocalizations.of(context)!.serverAddress),
|
||||||
),
|
SizedBox(
|
||||||
CwtchLabel(label: AppLocalizations.of(context)!.serverAddress),
|
height: 20,
|
||||||
SizedBox(
|
),
|
||||||
height: 20,
|
SelectableText(serverInfoState.onion),
|
||||||
),
|
|
||||||
SelectableText(
|
|
||||||
serverInfoState.onion
|
|
||||||
),
|
|
||||||
|
|
||||||
// Description
|
// Description
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
CwtchLabel(label: AppLocalizations.of(context)!.serverDescriptionLabel),
|
CwtchLabel(label: AppLocalizations.of(context)!.serverDescriptionLabel),
|
||||||
Text(AppLocalizations.of(context)!.serverDescriptionDescription),
|
Text(AppLocalizations.of(context)!.serverDescriptionDescription),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
CwtchButtonTextField(
|
CwtchButtonTextField(
|
||||||
controller: ctrlrDesc,
|
controller: ctrlrDesc,
|
||||||
readonly: false,
|
readonly: false,
|
||||||
tooltip: AppLocalizations.of(context)!.saveBtn,
|
tooltip: AppLocalizations.of(context)!.saveBtn,
|
||||||
labelText: AppLocalizations.of(context)!.fieldDescriptionLabel,
|
labelText: AppLocalizations.of(context)!.fieldDescriptionLabel,
|
||||||
icon: Icon(Icons.save),
|
icon: Icon(Icons.save),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profile.onion, serverInfoState.identifier, "server.description", ctrlrDesc.text);
|
Provider.of<FlwtchState>(context, listen: false).cwtch.SetConversationAttribute(profile.onion, serverInfoState.identifier, "server.description", ctrlrDesc.text);
|
||||||
serverInfoState.updateDescription(ctrlrDesc.text);
|
serverInfoState.updateDescription(ctrlrDesc.text);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
|
|
||||||
Padding(padding: EdgeInsets.all(8), child: Text( AppLocalizations.of(context)!.groupsOnThisServerLabel),),
|
Padding(
|
||||||
Expanded(child: _buildGroupsList(serverInfoState))
|
padding: EdgeInsets.all(8),
|
||||||
])));
|
child: Text(AppLocalizations.of(context)!.groupsOnThisServerLabel),
|
||||||
|
),
|
||||||
});
|
Expanded(child: _buildGroupsList(serverInfoState))
|
||||||
|
])));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildGroupsList(RemoteServerInfoState serverInfoState) {
|
Widget _buildGroupsList(RemoteServerInfoState serverInfoState) {
|
||||||
final tiles = serverInfoState.groups.map((ContactInfoState group) {
|
final tiles = serverInfoState.groups.map(
|
||||||
return ChangeNotifierProvider<ContactInfoState>.value(
|
(ContactInfoState group) {
|
||||||
value: group,
|
return ChangeNotifierProvider<ContactInfoState>.value(
|
||||||
builder: (context, child) => RepaintBoundary(child: _buildGroupRow(group)), // ServerRow()),
|
value: group,
|
||||||
);
|
builder: (context, child) => RepaintBoundary(child: _buildGroupRow(group)), // ServerRow()),
|
||||||
},
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
final divided = ListTile.divideTiles(
|
final divided = ListTile.divideTiles(
|
||||||
|
@ -126,26 +125,22 @@ class _RemoteServerViewState extends State<RemoteServerView> {
|
||||||
Widget _buildGroupRow(ContactInfoState group) {
|
Widget _buildGroupRow(ContactInfoState group) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(6.0), //border size
|
padding: const EdgeInsets.all(6.0), //border size
|
||||||
child: Column(
|
child: Column(children: [
|
||||||
children: [
|
Text(
|
||||||
Text(
|
group.nickname,
|
||||||
group.nickname,
|
style: Provider.of<FlwtchState>(context).biggerFont.apply(color: Provider.of<Settings>(context).theme.portraitOnlineBorderColor()),
|
||||||
style: Provider.of<FlwtchState>(context).biggerFont.apply(color: Provider.of<Settings>(context).theme.portraitOnlineBorderColor()),
|
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(
|
child: Text(
|
||||||
child: Text(
|
group.onion,
|
||||||
group.onion,
|
softWrap: true,
|
||||||
softWrap: true,
|
overflow: TextOverflow.ellipsis,
|
||||||
overflow: TextOverflow.ellipsis,
|
style: TextStyle(color: Provider.of<Settings>(context).theme.portraitOnlineBorderColor()),
|
||||||
style: TextStyle(color: Provider.of<Settings>(context).theme.portraitOnlineBorderColor()),
|
)))
|
||||||
)))
|
]));
|
||||||
])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,26 @@ class FileBubbleState extends State<FileBubble> {
|
||||||
var borderRadiousEh = 15.0;
|
var borderRadiousEh = 15.0;
|
||||||
var showFileSharing = Provider.of<Settings>(context).isExperimentEnabled(FileSharingExperiment);
|
var showFileSharing = Provider.of<Settings>(context).isExperimentEnabled(FileSharingExperiment);
|
||||||
var prettyDate = DateFormat.yMd(Platform.localeName).add_jm().format(Provider.of<MessageMetadata>(context).timestamp);
|
var prettyDate = DateFormat.yMd(Platform.localeName).add_jm().format(Provider.of<MessageMetadata>(context).timestamp);
|
||||||
|
var downloadComplete = Provider.of<ProfileInfoState>(context).downloadComplete(widget.fileKey());
|
||||||
|
var downloadInterrupted = Provider.of<ProfileInfoState>(context).downloadInterrupted(widget.fileKey());
|
||||||
|
|
||||||
|
if (downloadInterrupted) {
|
||||||
|
Provider.of<FlwtchState>(context, listen: false).cwtch.CheckDownloadStatus(Provider.of<ProfileInfoState>(context, listen: false).onion, widget.fileKey());
|
||||||
|
}
|
||||||
|
var path = Provider.of<ProfileInfoState>(context).downloadFinalPath(widget.fileKey());
|
||||||
|
if (downloadComplete) {
|
||||||
|
var lpath = path!.toLowerCase();
|
||||||
|
if (lpath.endsWith("jpg") || lpath.endsWith("jpeg") || lpath.endsWith("png") || lpath.endsWith("gif") || lpath.endsWith("webp") || lpath.endsWith("bmp")) {
|
||||||
|
if (myFile == null) {
|
||||||
|
setState(() {
|
||||||
|
myFile = new File(path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var downloadActive = Provider.of<ProfileInfoState>(context).downloadActive(widget.fileKey());
|
||||||
|
var downloadGotManifest = Provider.of<ProfileInfoState>(context).downloadGotManifest(widget.fileKey());
|
||||||
|
|
||||||
// If the sender is not us, then we want to give them a nickname...
|
// If the sender is not us, then we want to give them a nickname...
|
||||||
var senderDisplayStr = "";
|
var senderDisplayStr = "";
|
||||||
|
@ -61,85 +81,76 @@ class FileBubbleState extends State<FileBubble> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
var wdgSender = Center(
|
var wdgSender = Center(
|
||||||
widthFactor: 1,
|
|
||||||
child: SelectableText(senderDisplayStr + '\u202F',
|
|
||||||
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor())));
|
|
||||||
|
|
||||||
var isPreview = false;
|
|
||||||
var wdgMessage = !showFileSharing
|
|
||||||
? Text(AppLocalizations.of(context)!.messageEnableFileSharing)
|
|
||||||
: fromMe
|
|
||||||
? senderFileChrome(AppLocalizations.of(context)!.messageFileSent, widget.nameSuggestion, widget.rootHash, widget.fileSize)
|
|
||||||
: (fileChrome(AppLocalizations.of(context)!.messageFileOffered + ":", widget.nameSuggestion, widget.rootHash, widget.fileSize,
|
|
||||||
Provider.of<ProfileInfoState>(context).downloadSpeed(widget.fileKey())));
|
|
||||||
Widget wdgDecorations;
|
|
||||||
if (!showFileSharing) {
|
|
||||||
wdgDecorations = Text('\u202F');
|
|
||||||
} else if (fromMe) {
|
|
||||||
wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageMetadata>(context).ackd, errored: Provider.of<MessageMetadata>(context).error, fromMe: fromMe, prettyDate: prettyDate);
|
|
||||||
} else if (Provider.of<ProfileInfoState>(context).downloadComplete(widget.fileKey())) {
|
|
||||||
// in this case, whatever marked download.complete would have also set the path
|
|
||||||
var path = Provider.of<ProfileInfoState>(context).downloadFinalPath(widget.fileKey())!;
|
|
||||||
var lpath = path.toLowerCase();
|
|
||||||
if (lpath.endsWith("jpg") || lpath.endsWith("jpeg") || lpath.endsWith("png") || lpath.endsWith("gif") || lpath.endsWith("webp") || lpath.endsWith("bmp")) {
|
|
||||||
if (myFile == null) {
|
|
||||||
setState(() {
|
|
||||||
myFile = new File(path);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
isPreview = true;
|
|
||||||
wdgDecorations = GestureDetector(
|
|
||||||
child: Image.file(
|
|
||||||
myFile!,
|
|
||||||
cacheWidth: 2048, // limit the amount of space the image can decode too, we keep this high-ish to allow quality previews...
|
|
||||||
filterQuality: FilterQuality.medium,
|
|
||||||
fit: BoxFit.fill,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
width: constraints.maxWidth,
|
|
||||||
isAntiAlias: false,
|
|
||||||
errorBuilder: (context, error, stackTrace) {
|
|
||||||
return MalformedBubble();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
pop(myFile!, wdgMessage);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
wdgDecorations = Text(AppLocalizations.of(context)!.fileSavedTo + ': ' + path + '\u202F');
|
|
||||||
}
|
|
||||||
} else if (Provider.of<ProfileInfoState>(context).downloadActive(widget.fileKey())) {
|
|
||||||
if (!Provider.of<ProfileInfoState>(context).downloadGotManifest(widget.fileKey())) {
|
|
||||||
wdgDecorations = Text(AppLocalizations.of(context)!.retrievingManifestMessage + '\u202F');
|
|
||||||
} else {
|
|
||||||
wdgDecorations = LinearProgressIndicator(
|
|
||||||
value: Provider.of<ProfileInfoState>(context).downloadProgress(widget.fileKey()),
|
|
||||||
color: Provider.of<Settings>(context).theme.defaultButtonActiveColor(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (flagStarted) {
|
|
||||||
// in this case, the download was done in a previous application launch,
|
|
||||||
// so we probably have to request an info lookup
|
|
||||||
if (!Provider.of<ProfileInfoState>(context).downloadInterrupted(widget.fileKey())) {
|
|
||||||
wdgDecorations = Text(AppLocalizations.of(context)!.fileCheckingStatus + '...' + '\u202F');
|
|
||||||
Provider.of<FlwtchState>(context, listen: false).cwtch.CheckDownloadStatus(Provider.of<ProfileInfoState>(context, listen: false).onion, widget.fileKey());
|
|
||||||
} else {
|
|
||||||
var path = Provider.of<ProfileInfoState>(context).downloadFinalPath(widget.fileKey()) ?? "";
|
|
||||||
wdgDecorations = Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
|
||||||
Text(AppLocalizations.of(context)!.fileInterrupted + ': ' + path + '\u202F'),
|
|
||||||
ElevatedButton(onPressed: _btnResume, child: Text(AppLocalizations.of(context)!.verfiyResumeButton))
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wdgDecorations = Center(
|
|
||||||
widthFactor: 1,
|
widthFactor: 1,
|
||||||
child: Wrap(children: [
|
child: SelectableText(senderDisplayStr + '\u202F',
|
||||||
Padding(padding: EdgeInsets.all(5), child: ElevatedButton(child: Text(AppLocalizations.of(context)!.downloadFileButton + '\u202F'), onPressed: _btnAccept)),
|
style: TextStyle(fontSize: 9.0, color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeTextColor() : Provider.of<Settings>(context).theme.messageFromOtherTextColor())));
|
||||||
]));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var isPreview = false;
|
||||||
|
var wdgMessage = !showFileSharing
|
||||||
|
? Text(AppLocalizations.of(context)!.messageEnableFileSharing)
|
||||||
|
: fromMe
|
||||||
|
? senderFileChrome(AppLocalizations.of(context)!.messageFileSent, widget.nameSuggestion, widget.rootHash, widget.fileSize)
|
||||||
|
: (fileChrome(AppLocalizations.of(context)!.messageFileOffered + ":", widget.nameSuggestion, widget.rootHash, widget.fileSize,
|
||||||
|
Provider.of<ProfileInfoState>(context).downloadSpeed(widget.fileKey())));
|
||||||
|
Widget wdgDecorations;
|
||||||
|
if (!showFileSharing) {
|
||||||
|
wdgDecorations = Text('\u202F');
|
||||||
|
} else if (fromMe) {
|
||||||
|
wdgDecorations = MessageBubbleDecoration(ackd: Provider.of<MessageMetadata>(context).ackd, errored: Provider.of<MessageMetadata>(context).error, fromMe: fromMe, prettyDate: prettyDate);
|
||||||
|
} else if (downloadComplete) {
|
||||||
|
// in this case, whatever marked download.complete would have also set the path
|
||||||
|
var lpath = path!.toLowerCase();
|
||||||
|
if (lpath.endsWith("jpg") || lpath.endsWith("jpeg") || lpath.endsWith("png") || lpath.endsWith("gif") || lpath.endsWith("webp") || lpath.endsWith("bmp")) {
|
||||||
|
isPreview = true;
|
||||||
|
wdgDecorations = GestureDetector(
|
||||||
|
child: Image.file(
|
||||||
|
myFile!,
|
||||||
|
cacheWidth: 2048, // limit the amount of space the image can decode too, we keep this high-ish to allow quality previews...
|
||||||
|
filterQuality: FilterQuality.medium,
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
width: constraints.maxWidth,
|
||||||
|
isAntiAlias: false,
|
||||||
|
errorBuilder: (context, error, stackTrace) {
|
||||||
|
return MalformedBubble();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
pop(myFile!, wdgMessage);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
wdgDecorations = Text(AppLocalizations.of(context)!.fileSavedTo + ': ' + path + '\u202F');
|
||||||
|
}
|
||||||
|
} else if (downloadActive) {
|
||||||
|
if (!downloadGotManifest) {
|
||||||
|
wdgDecorations = Text(AppLocalizations.of(context)!.retrievingManifestMessage + '\u202F');
|
||||||
|
} else {
|
||||||
|
wdgDecorations = LinearProgressIndicator(
|
||||||
|
value: Provider.of<ProfileInfoState>(context).downloadProgress(widget.fileKey()),
|
||||||
|
color: Provider.of<Settings>(context).theme.defaultButtonActiveColor(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (flagStarted) {
|
||||||
|
// in this case, the download was done in a previous application launch,
|
||||||
|
// so we probably have to request an info lookup
|
||||||
|
if (!downloadInterrupted) {
|
||||||
|
wdgDecorations = Text(AppLocalizations.of(context)!.fileCheckingStatus + '...' + '\u202F');
|
||||||
|
} else {
|
||||||
|
var path = Provider.of<ProfileInfoState>(context).downloadFinalPath(widget.fileKey()) ?? "";
|
||||||
|
wdgDecorations = Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
|
Text(AppLocalizations.of(context)!.fileInterrupted + ': ' + path + '\u202F'),
|
||||||
|
ElevatedButton(onPressed: _btnResume, child: Text(AppLocalizations.of(context)!.verfiyResumeButton))
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wdgDecorations = Center(
|
||||||
|
widthFactor: 1,
|
||||||
|
child: Wrap(children: [
|
||||||
|
Padding(padding: EdgeInsets.all(5), child: ElevatedButton(child: Text(AppLocalizations.of(context)!.downloadFileButton + '\u202F'), onPressed: _btnAccept)),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
constraints: constraints,
|
constraints: constraints,
|
||||||
|
@ -193,7 +204,7 @@ class FileBubbleState extends State<FileBubble> {
|
||||||
Provider.of<ProfileInfoState>(context, listen: false).downloadInit(widget.fileKey(), (widget.fileSize / 4096).ceil());
|
Provider.of<ProfileInfoState>(context, listen: false).downloadInit(widget.fileKey(), (widget.fileSize / 4096).ceil());
|
||||||
Provider.of<FlwtchState>(context, listen: false).cwtch.SetMessageAttribute(profileOnion, conversation, 0, idx, "file-downloaded", "true");
|
Provider.of<FlwtchState>(context, listen: false).cwtch.SetMessageAttribute(profileOnion, conversation, 0, idx, "file-downloaded", "true");
|
||||||
//Provider.of<MessageMetadata>(context, listen: false).flags |= 0x02;
|
//Provider.of<MessageMetadata>(context, listen: false).flags |= 0x02;
|
||||||
ContactInfoState? contact = Provider.of<ProfileInfoState>(context).contactList.findContact(Provider.of<MessageMetadata>(context).senderHandle);
|
ContactInfoState? contact = Provider.of<ProfileInfoState>(context, listen: false).contactList.findContact(Provider.of<MessageMetadata>(context).senderHandle);
|
||||||
if (contact != null) {
|
if (contact != null) {
|
||||||
Provider.of<FlwtchState>(context, listen: false).cwtch.DownloadFile(profileOnion, contact.identifier, file.path, manifestPath, widget.fileKey());
|
Provider.of<FlwtchState>(context, listen: false).cwtch.DownloadFile(profileOnion, contact.identifier, file.path, manifestPath, widget.fileKey());
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,40 +28,40 @@ class _CwtchFolderPickerState extends State<CwtchFolderPicker> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
margin: EdgeInsets.all(10),
|
margin: EdgeInsets.all(10),
|
||||||
padding: EdgeInsets.all(2),
|
padding: EdgeInsets.all(2),
|
||||||
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
CwtchLabel(label: widget.label),
|
CwtchLabel(label: widget.label),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
),
|
),
|
||||||
CwtchButtonTextField(
|
CwtchButtonTextField(
|
||||||
controller: ctrlrVal,
|
controller: ctrlrVal,
|
||||||
readonly: Platform.isAndroid,
|
readonly: Platform.isAndroid,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
var selectedDirectory = await getDirectoryPath();
|
|
||||||
if (selectedDirectory != null) {
|
|
||||||
//File directory = File(selectedDirectory);
|
|
||||||
selectedDirectory += "/";
|
|
||||||
ctrlrVal.text = selectedDirectory;
|
|
||||||
if (widget.onSave != null) {
|
|
||||||
widget.onSave!(selectedDirectory);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// User canceled the picker
|
try {
|
||||||
}
|
var selectedDirectory = await getDirectoryPath();
|
||||||
} catch (e) {
|
if (selectedDirectory != null) {
|
||||||
print(e);
|
//File directory = File(selectedDirectory);
|
||||||
}
|
selectedDirectory += "/";
|
||||||
},
|
ctrlrVal.text = selectedDirectory;
|
||||||
icon: Icon(Icons.folder),
|
if (widget.onSave != null) {
|
||||||
tooltip: "Browse",//todo: l18n
|
widget.onSave!(selectedDirectory);
|
||||||
)
|
}
|
||||||
]));
|
} else {
|
||||||
|
// User canceled the picker
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: Icon(Icons.folder),
|
||||||
|
tooltip: "Browse", //todo: l18n
|
||||||
|
)
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,46 +23,42 @@ class _RemoteServerRowState extends State<RemoteServerRow> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var server = Provider.of<RemoteServerInfoState>(context);
|
var server = Provider.of<RemoteServerInfoState>(context);
|
||||||
var description = server.description.isNotEmpty ? server.description : server.onion;
|
var description = server.description.isNotEmpty ? server.description : server.onion;
|
||||||
var running = server.status == "Synced";
|
var running = server.status == "Synced";
|
||||||
return Consumer<ProfileInfoState>(
|
return Consumer<ProfileInfoState>(builder: (context, profile, child) {
|
||||||
builder: (context, profile, child) {
|
return Card(
|
||||||
return Card(clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
margin: EdgeInsets.all(0.0),
|
margin: EdgeInsets.all(0.0),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
child: Row(
|
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(6.0), //border size
|
||||||
|
child: Icon(CwtchIcons.dns_24px,
|
||||||
|
color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor(), size: 64)),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Text(
|
||||||
padding: const EdgeInsets.all(6.0), //border size
|
description,
|
||||||
child: Icon(CwtchIcons.dns_24px,
|
semanticsLabel: description,
|
||||||
color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor(),
|
style: Provider.of<FlwtchState>(context)
|
||||||
size: 64)
|
.biggerFont
|
||||||
|
.apply(color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
|
||||||
|
softWrap: true,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
Expanded(
|
Visibility(
|
||||||
child: Column(
|
visible: !Provider.of<Settings>(context).streamerMode,
|
||||||
children: [
|
child: ExcludeSemantics(
|
||||||
Text(
|
child: Text(
|
||||||
description,
|
server.onion,
|
||||||
semanticsLabel: description,
|
softWrap: true,
|
||||||
style: Provider.of<FlwtchState>(context).biggerFont.apply(color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
|
overflow: TextOverflow.ellipsis,
|
||||||
softWrap: true,
|
style: TextStyle(color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
|
||||||
overflow: TextOverflow.ellipsis,
|
)))
|
||||||
),
|
],
|
||||||
Visibility(
|
)),
|
||||||
visible: !Provider.of<Settings>(context).streamerMode,
|
]),
|
||||||
child: ExcludeSemantics(
|
|
||||||
child: Text(
|
|
||||||
server.onion,
|
|
||||||
softWrap: true,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(color: running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
|
|
||||||
)))
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
|
|
||||||
]),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.of(context).push(MaterialPageRoute<void>(
|
Navigator.of(context).push(MaterialPageRoute<void>(
|
||||||
settings: RouteSettings(name: "remoteserverview"),
|
settings: RouteSettings(name: "remoteserverview"),
|
||||||
|
@ -72,7 +68,7 @@ class _RemoteServerRowState extends State<RemoteServerRow> {
|
||||||
child: RemoteServerView(),
|
child: RemoteServerView(),
|
||||||
);
|
);
|
||||||
}));
|
}));
|
||||||
}
|
}));
|
||||||
));});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,58 +26,57 @@ class _ServerRowState extends State<ServerRow> {
|
||||||
margin: EdgeInsets.all(0.0),
|
margin: EdgeInsets.all(0.0),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(6.0), //border size
|
padding: const EdgeInsets.all(6.0), //border size
|
||||||
child: Icon(CwtchIcons.dns_24px,
|
child: Icon(CwtchIcons.dns_24px,
|
||||||
color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor(), size: 64)),
|
color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor(), size: 64)),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
server.description,
|
server.description,
|
||||||
semanticsLabel: server.description,
|
semanticsLabel: server.description,
|
||||||
style: Provider.of<FlwtchState>(context)
|
style: Provider.of<FlwtchState>(context)
|
||||||
.biggerFont
|
.biggerFont
|
||||||
.apply(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
|
.apply(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
|
||||||
softWrap: true,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
Visibility(
|
|
||||||
visible: !Provider.of<Settings>(context).streamerMode,
|
|
||||||
child: ExcludeSemantics(
|
|
||||||
child: Text(
|
|
||||||
server.onion,
|
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
|
),
|
||||||
)))
|
Visibility(
|
||||||
],
|
visible: !Provider.of<Settings>(context).streamerMode,
|
||||||
)),
|
child: ExcludeSemantics(
|
||||||
|
child: Text(
|
||||||
|
server.onion,
|
||||||
|
softWrap: true,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(color: server.running ? Provider.of<Settings>(context).theme.portraitOnlineBorderColor() : Provider.of<Settings>(context).theme.portraitOfflineBorderColor()),
|
||||||
|
)))
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
|
||||||
// Copy server button
|
// Copy server button
|
||||||
IconButton(
|
IconButton(
|
||||||
enableFeedback: true,
|
enableFeedback: true,
|
||||||
tooltip: AppLocalizations.of(context)!.copyServerKeys,
|
tooltip: AppLocalizations.of(context)!.copyServerKeys,
|
||||||
icon: Icon(CwtchIcons.address_copy_2, color: Provider.of<Settings>(context).current().mainTextColor()),
|
icon: Icon(CwtchIcons.address_copy_2, color: Provider.of<Settings>(context).current().mainTextColor()),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Clipboard.setData(new ClipboardData(text: server.serverBundle));
|
Clipboard.setData(new ClipboardData(text: server.serverBundle));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
// Edit button
|
// Edit button
|
||||||
IconButton(
|
IconButton(
|
||||||
enableFeedback: true,
|
enableFeedback: true,
|
||||||
tooltip: AppLocalizations.of(context)!.editServerTitle,
|
tooltip: AppLocalizations.of(context)!.editServerTitle,
|
||||||
icon: Icon(Icons.create, color: Provider.of<Settings>(context).current().mainTextColor()),
|
icon: Icon(Icons.create, color: Provider.of<Settings>(context).current().mainTextColor()),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
_pushEditServer(server);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]),
|
||||||
|
onTap: () {
|
||||||
_pushEditServer(server);
|
_pushEditServer(server);
|
||||||
},
|
}));
|
||||||
)
|
|
||||||
]),
|
|
||||||
onTap: () {
|
|
||||||
_pushEditServer(server);
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pushEditServer(ServerInfoState server) {
|
void _pushEditServer(ServerInfoState server) {
|
||||||
|
|
Loading…
Reference in New Issue