Merge pull request 'Format, Context Binding and Check if File Exists in File Bubble' (#447) from file-fixes into trunk
continuous-integration/drone/push Build is pending
Details
continuous-integration/drone/push Build is pending
Details
Reviewed-on: #447 Reviewed-by: Dan Ballard <dan@openprivacy.ca>
This commit is contained in:
commit
9d8f73ac00
|
@ -215,8 +215,9 @@ class CwtchFfi implements Cwtch {
|
||||||
// ignore: non_constant_identifier_names
|
// ignore: non_constant_identifier_names
|
||||||
final StartCwtch = startCwtchC.asFunction<StartCwtchFn>();
|
final StartCwtch = startCwtchC.asFunction<StartCwtchFn>();
|
||||||
|
|
||||||
final ut8CwtchDir = cwtchDir.toNativeUtf8();
|
final utf8CwtchDir = cwtchDir.toNativeUtf8();
|
||||||
StartCwtch(ut8CwtchDir, ut8CwtchDir.length, bundledTor.toNativeUtf8(), bundledTor.length);
|
StartCwtch(utf8CwtchDir, utf8CwtchDir.length, bundledTor.toNativeUtf8(), bundledTor.length);
|
||||||
|
malloc.free(utf8CwtchDir);
|
||||||
|
|
||||||
// Spawn an isolate to listen to events from libcwtch-go and then dispatch them when received on main thread to cwtchNotifier
|
// Spawn an isolate to listen to events from libcwtch-go and then dispatch them when received on main thread to cwtchNotifier
|
||||||
cwtchIsolate = await Isolate.spawn(_checkAppbusEvents, _receivePort.sendPort);
|
cwtchIsolate = await Isolate.spawn(_checkAppbusEvents, _receivePort.sendPort);
|
||||||
|
@ -326,6 +327,7 @@ class CwtchFfi implements Cwtch {
|
||||||
String jsonMessage = jsonMessageBytes.toDartString();
|
String jsonMessage = jsonMessageBytes.toDartString();
|
||||||
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes);
|
_UnsafeFreePointerAnyUseOfThisFunctionMustBeDoubleApproved(jsonMessageBytes);
|
||||||
malloc.free(utf8profile);
|
malloc.free(utf8profile);
|
||||||
|
|
||||||
return jsonMessage;
|
return jsonMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ class MessageCache extends ChangeNotifier {
|
||||||
void addFrontIndexGap(int count, int lastSeenId) {
|
void addFrontIndexGap(int count, int lastSeenId) {
|
||||||
// scan across indexed message the unread count amount (that's the last time UI/BE acked a message)
|
// scan across indexed message the unread count amount (that's the last time UI/BE acked a message)
|
||||||
// if we find the last seen ID, the diff of unread count is what's unsynced
|
// if we find the last seen ID, the diff of unread count is what's unsynced
|
||||||
for(var i = 0; i < (count+1) && i < cacheByIndex.length; i++) {
|
for (var i = 0; i < (count + 1) && i < cacheByIndex.length; i++) {
|
||||||
if (this.cacheByIndex[i].messageId == lastSeenId) {
|
if (this.cacheByIndex[i].messageId == lastSeenId) {
|
||||||
// we have found the matching lastSeenId so we can calculate the unsynced as the unread messages before it
|
// we have found the matching lastSeenId so we can calculate the unsynced as the unread messages before it
|
||||||
this._indexUnsynced = count - i;
|
this._indexUnsynced = count - i;
|
||||||
|
|
|
@ -350,4 +350,9 @@ class ProfileInfoState extends ChangeNotifier {
|
||||||
int cacheMemUsage() {
|
int cacheMemUsage() {
|
||||||
return _contacts.cacheMemUsage();
|
return _contacts.cacheMemUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void downloadReset(String fileKey) {
|
||||||
|
this._downloads.remove(fileKey);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,10 @@ class _ContactsViewState extends State<ContactsView> {
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: _modalAddImportChoice,
|
onPressed: _modalAddImportChoice,
|
||||||
tooltip: AppLocalizations.of(context)!.tooltipAddContact,
|
tooltip: AppLocalizations.of(context)!.tooltipAddContact,
|
||||||
child: Icon(CwtchIcons.person_add_alt_1_24px, color: Provider.of<Settings>(context).theme.defaultButtonTextColor,),
|
child: Icon(
|
||||||
|
CwtchIcons.person_add_alt_1_24px,
|
||||||
|
color: Provider.of<Settings>(context).theme.defaultButtonTextColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: showSearchBar || Provider.of<ContactListState>(context).isFiltered ? _buildFilterable() : _buildContactList());
|
body: showSearchBar || Provider.of<ContactListState>(context).isFiltered ? _buildFilterable() : _buildContactList());
|
||||||
}
|
}
|
||||||
|
|
|
@ -464,7 +464,7 @@ class _GlobalSettingsViewState extends State<GlobalSettingsView> {
|
||||||
Visibility(
|
Visibility(
|
||||||
visible: EnvironmentConfig.BUILD_VER == dev_version && !Platform.isAndroid,
|
visible: EnvironmentConfig.BUILD_VER == dev_version && !Platform.isAndroid,
|
||||||
child: FutureBuilder(
|
child: FutureBuilder(
|
||||||
future: EnvironmentConfig.BUILD_VER != dev_version ||Platform.isAndroid ? null : Provider.of<FlwtchState>(context).cwtch.GetDebugInfo(),
|
future: EnvironmentConfig.BUILD_VER != dev_version || Platform.isAndroid ? null : Provider.of<FlwtchState>(context).cwtch.GetDebugInfo(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
return Column(
|
return Column(
|
||||||
|
|
|
@ -183,7 +183,9 @@ class _GroupSettingsViewState extends State<GroupSettingsView> {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showAlertDialog(context);
|
showAlertDialog(context);
|
||||||
},
|
},
|
||||||
style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.backgroundPaneColor), foregroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.mainTextColor)),
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.backgroundPaneColor),
|
||||||
|
foregroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.mainTextColor)),
|
||||||
icon: Icon(CwtchIcons.leave_group),
|
icon: Icon(CwtchIcons.leave_group),
|
||||||
label: Text(
|
label: Text(
|
||||||
AppLocalizations.of(context)!.leaveConversation,
|
AppLocalizations.of(context)!.leaveConversation,
|
||||||
|
|
|
@ -269,7 +269,9 @@ class _PeerSettingsViewState extends State<PeerSettingsView> {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showAlertDialog(context);
|
showAlertDialog(context);
|
||||||
},
|
},
|
||||||
style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.backgroundPaneColor), foregroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.mainTextColor)),
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.backgroundPaneColor),
|
||||||
|
foregroundColor: MaterialStateProperty.all(Provider.of<Settings>(context).theme.mainTextColor)),
|
||||||
icon: Icon(CwtchIcons.leave_group),
|
icon: Icon(CwtchIcons.leave_group),
|
||||||
label: Text(
|
label: Text(
|
||||||
AppLocalizations.of(context)!.leaveConversation,
|
AppLocalizations.of(context)!.leaveConversation,
|
||||||
|
|
|
@ -48,7 +48,7 @@ class FileBubbleState extends State<FileBubble> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var fromMe = Provider.of<MessageMetadata>(context).senderHandle == Provider.of<ProfileInfoState>(context).onion;
|
var fromMe = Provider.of<MessageMetadata>(context).senderHandle == Provider.of<ProfileInfoState>(context).onion;
|
||||||
var flagStarted = Provider.of<MessageMetadata>(context).attributes["file-downloaded"] == "true";
|
var flagStarted = Provider.of<MessageMetadata>(context).attributes["file-downloaded"] == "true";
|
||||||
var borderRadiousEh = 15.0;
|
var borderRadius = 15.0;
|
||||||
var showFileSharing = Provider.of<Settings>(context).isExperimentEnabled(FileSharingExperiment);
|
var showFileSharing = Provider.of<Settings>(context).isExperimentEnabled(FileSharingExperiment);
|
||||||
DateTime messageDate = Provider.of<MessageMetadata>(context).timestamp;
|
DateTime messageDate = Provider.of<MessageMetadata>(context).timestamp;
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class FileBubbleState extends State<FileBubble> {
|
||||||
var path = Provider.of<ProfileInfoState>(context).downloadFinalPath(widget.fileKey());
|
var path = Provider.of<ProfileInfoState>(context).downloadFinalPath(widget.fileKey());
|
||||||
|
|
||||||
// If we haven't stored the filepath in message attributes then save it
|
// If we haven't stored the filepath in message attributes then save it
|
||||||
if (metadata.attributes["filepath"] != null) {
|
if (metadata.attributes["filepath"] != null && metadata.attributes["filepath"].toString().isNotEmpty) {
|
||||||
path = metadata.attributes["filepath"];
|
path = metadata.attributes["filepath"];
|
||||||
} else if (path != null && metadata.attributes["filepath"] == null) {
|
} else if (path != null && metadata.attributes["filepath"] == null) {
|
||||||
Provider.of<FlwtchState>(context).cwtch.SetMessageAttribute(metadata.profileOnion, metadata.conversationIdentifier, 0, metadata.messageID, "filepath", path);
|
Provider.of<FlwtchState>(context).cwtch.SetMessageAttribute(metadata.profileOnion, metadata.conversationIdentifier, 0, metadata.messageID, "filepath", path);
|
||||||
|
@ -72,6 +72,21 @@ class FileBubbleState extends State<FileBubble> {
|
||||||
if (myFile == null) {
|
if (myFile == null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
myFile = new File(path!);
|
myFile = new File(path!);
|
||||||
|
|
||||||
|
// reset
|
||||||
|
if (myFile?.existsSync() == false) {
|
||||||
|
myFile = null;
|
||||||
|
Provider.of<ProfileInfoState>(context).downloadReset(widget.fileKey());
|
||||||
|
Provider.of<MessageMetadata>(context).attributes["filepath"] = null;
|
||||||
|
Provider.of<MessageMetadata>(context).attributes["file-downloaded"] = "false";
|
||||||
|
Provider.of<MessageMetadata>(context).attributes["file-missing"] = "true";
|
||||||
|
Provider.of<FlwtchState>(context).cwtch.SetMessageAttribute(metadata.profileOnion, metadata.conversationIdentifier, 0, metadata.messageID, "file-downloaded", "false");
|
||||||
|
Provider.of<FlwtchState>(context).cwtch.SetMessageAttribute(metadata.profileOnion, metadata.conversationIdentifier, 0, metadata.messageID, "filepath", "");
|
||||||
|
Provider.of<FlwtchState>(context).cwtch.SetMessageAttribute(metadata.profileOnion, metadata.conversationIdentifier, 0, metadata.messageID, "file-missing", "true");
|
||||||
|
} else {
|
||||||
|
Provider.of<MessageMetadata>(context).attributes["file-missing"] = "false";
|
||||||
|
Provider.of<FlwtchState>(context).cwtch.SetMessageAttribute(metadata.profileOnion, metadata.conversationIdentifier, 0, metadata.messageID, "file-missing", "false");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +137,7 @@ class FileBubbleState extends State<FileBubble> {
|
||||||
padding: EdgeInsets.all(1.0),
|
padding: EdgeInsets.all(1.0),
|
||||||
child: Image.file(
|
child: Image.file(
|
||||||
myFile!,
|
myFile!,
|
||||||
cacheWidth: 2048,
|
cacheWidth: (MediaQuery.of(bcontext).size.width * 0.6).floor(),
|
||||||
// limit the amount of space the image can decode too, we keep this high-ish to allow quality previews...
|
// limit the amount of space the image can decode too, we keep this high-ish to allow quality previews...
|
||||||
filterQuality: FilterQuality.medium,
|
filterQuality: FilterQuality.medium,
|
||||||
fit: BoxFit.scaleDown,
|
fit: BoxFit.scaleDown,
|
||||||
|
@ -167,7 +182,9 @@ class FileBubbleState extends State<FileBubble> {
|
||||||
}
|
}
|
||||||
} else if (!senderIsContact) {
|
} else if (!senderIsContact) {
|
||||||
wdgDecorations = Text(AppLocalizations.of(context)!.msgAddToAccept);
|
wdgDecorations = Text(AppLocalizations.of(context)!.msgAddToAccept);
|
||||||
} else if (!widget.isAuto) {
|
} else if (!widget.isAuto || Provider.of<MessageMetadata>(context).attributes["file-missing"] == "false") {
|
||||||
|
//Note: we need this second case to account for scenarios where a user deletes the downloaded file, we won't automatically
|
||||||
|
// fetch it again, so we need to offer the user the ability to restart..
|
||||||
wdgDecorations = Visibility(
|
wdgDecorations = Visibility(
|
||||||
visible: widget.interactive,
|
visible: widget.interactive,
|
||||||
child: Center(
|
child: Center(
|
||||||
|
@ -185,10 +202,10 @@ class FileBubbleState extends State<FileBubble> {
|
||||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor,
|
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor,
|
||||||
border: Border.all(color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor, width: 1),
|
border: Border.all(color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor, width: 1),
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
topLeft: Radius.circular(borderRadiousEh),
|
topLeft: Radius.circular(borderRadius),
|
||||||
topRight: Radius.circular(borderRadiousEh),
|
topRight: Radius.circular(borderRadius),
|
||||||
bottomLeft: fromMe ? Radius.circular(borderRadiousEh) : Radius.zero,
|
bottomLeft: fromMe ? Radius.circular(borderRadius) : Radius.zero,
|
||||||
bottomRight: fromMe ? Radius.zero : Radius.circular(borderRadiousEh),
|
bottomRight: fromMe ? Radius.zero : Radius.circular(borderRadius),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|
|
@ -118,37 +118,37 @@ class MessageBubbleState extends State<MessageBubble> {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(AppLocalizations.of(context)!.clickableLinksWarning),
|
Text(AppLocalizations.of(bcontext)!.clickableLinksWarning),
|
||||||
Flex(direction: Axis.horizontal, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
|
Flex(direction: Axis.horizontal, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
|
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
child: Text(AppLocalizations.of(context)!.clickableLinksCopy, semanticsLabel: AppLocalizations.of(context)!.clickableLinksCopy),
|
child: Text(AppLocalizations.of(bcontext)!.clickableLinksCopy, semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinksCopy),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Clipboard.setData(new ClipboardData(text: link.url));
|
Clipboard.setData(new ClipboardData(text: link.url));
|
||||||
|
|
||||||
final snackBar = SnackBar(
|
final snackBar = SnackBar(
|
||||||
content: Text(AppLocalizations.of(context)!.copiedToClipboardNotification),
|
content: Text(AppLocalizations.of(bcontext)!.copiedToClipboardNotification),
|
||||||
);
|
);
|
||||||
|
|
||||||
Navigator.pop(bcontext);
|
Navigator.pop(bcontext);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
ScaffoldMessenger.of(bcontext).showSnackBar(snackBar);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
|
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
child: Text(AppLocalizations.of(context)!.clickableLinkOpen, semanticsLabel: AppLocalizations.of(context)!.clickableLinkOpen),
|
child: Text(AppLocalizations.of(bcontext)!.clickableLinkOpen, semanticsLabel: AppLocalizations.of(bcontext)!.clickableLinkOpen),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (await canLaunch(link.url)) {
|
if (await canLaunch(link.url)) {
|
||||||
await launch(link.url);
|
await launch(link.url);
|
||||||
Navigator.pop(bcontext);
|
Navigator.pop(bcontext);
|
||||||
} else {
|
} else {
|
||||||
final snackBar = SnackBar(
|
final snackBar = SnackBar(
|
||||||
content: Text(AppLocalizations.of(context)!.clickableLinkError),
|
content: Text(AppLocalizations.of(bcontext)!.clickableLinkError),
|
||||||
);
|
);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
ScaffoldMessenger.of(bcontext).showSnackBar(snackBar);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue