mirror of
https://github.com/liamcottle/reticulum-meshchat.git
synced 2026-04-28 00:20:48 +00:00
allow selecting delivery method before sending messages
This commit is contained in:
parent
8478fdb835
commit
018075eb12
3 changed files with 117 additions and 13 deletions
38
meshchat.py
38
meshchat.py
|
|
@ -1254,6 +1254,11 @@ class ReticulumMeshChat:
|
|||
# get request body as json
|
||||
data = await request.json()
|
||||
|
||||
# get delivery method
|
||||
delivery_method = None
|
||||
if "delivery_method" in data:
|
||||
delivery_method = data["delivery_method"]
|
||||
|
||||
# get data from json
|
||||
destination_hash = data["lxmf_message"]["destination_hash"]
|
||||
content = data["lxmf_message"]["content"]
|
||||
|
|
@ -1295,7 +1300,8 @@ class ReticulumMeshChat:
|
|||
content=content,
|
||||
image_field=image_field,
|
||||
audio_field=audio_field,
|
||||
file_attachments_field=file_attachments_field
|
||||
file_attachments_field=file_attachments_field,
|
||||
delivery_method=delivery_method
|
||||
)
|
||||
|
||||
return web.json_response({
|
||||
|
|
@ -2143,7 +2149,8 @@ class ReticulumMeshChat:
|
|||
async def send_message(self, destination_hash: str, content: str,
|
||||
image_field: LxmfImageField = None,
|
||||
audio_field: LxmfAudioField = None,
|
||||
file_attachments_field: LxmfFileAttachmentsField = None) -> LXMF.LXMessage:
|
||||
file_attachments_field: LxmfFileAttachmentsField = None,
|
||||
delivery_method: str = None) -> LXMF.LXMessage:
|
||||
|
||||
# convert destination hash to bytes
|
||||
destination_hash = bytes.fromhex(destination_hash)
|
||||
|
|
@ -2171,14 +2178,27 @@ class ReticulumMeshChat:
|
|||
# create destination for recipients lxmf delivery address
|
||||
lxmf_destination = RNS.Destination(destination_identity, RNS.Destination.OUT, RNS.Destination.SINGLE, "lxmf", "delivery")
|
||||
|
||||
# send messages over a direct link by default
|
||||
desired_delivery_method = LXMF.LXMessage.DIRECT
|
||||
if not self.message_router.delivery_link_available(destination_hash) and RNS.Identity.current_ratchet_id(destination_hash) != None:
|
||||
# since there's no link established to the destination, it's faster to send opportunistically
|
||||
# this is because it takes several packets to establish a link, and then we still have to send the message over it
|
||||
# oppotunistic mode will send the message in a single packet (if the message is small enough, otherwise it falls back to a direct link)
|
||||
# we will only do this if an encryption ratchet is available, so single packet delivery is more secure
|
||||
# determine how the user wants to send the message
|
||||
desired_delivery_method = None
|
||||
if delivery_method == "direct":
|
||||
desired_delivery_method = LXMF.LXMessage.DIRECT
|
||||
elif delivery_method == "opportunistic":
|
||||
desired_delivery_method = LXMF.LXMessage.OPPORTUNISTIC
|
||||
elif delivery_method == "propagated":
|
||||
desired_delivery_method = LXMF.LXMessage.PROPAGATED
|
||||
|
||||
# determine how to send the message if the user didn't provide a method
|
||||
if desired_delivery_method is None:
|
||||
|
||||
# send messages over a direct link by default
|
||||
desired_delivery_method = LXMF.LXMessage.DIRECT
|
||||
if not self.message_router.delivery_link_available(destination_hash) and RNS.Identity.current_ratchet_id(destination_hash) != None:
|
||||
|
||||
# since there's no link established to the destination, it's faster to send opportunistically
|
||||
# this is because it takes several packets to establish a link, and then we still have to send the message over it
|
||||
# oppotunistic mode will send the message in a single packet (if the message is small enough, otherwise it falls back to a direct link)
|
||||
# we will only do this if an encryption ratchet is available, so single packet delivery is more secure
|
||||
desired_delivery_method = LXMF.LXMessage.OPPORTUNISTIC
|
||||
|
||||
# create lxmf message
|
||||
lxmf_message = LXMF.LXMessage(lxmf_destination, self.local_lxmf_destination, content, desired_method=desired_delivery_method)
|
||||
|
|
|
|||
|
|
@ -332,10 +332,14 @@
|
|||
</div>
|
||||
|
||||
<!-- send message -->
|
||||
<button @click="sendMessage" :disabled="!canSendMessage" type="button" class="ml-auto my-auto inline-flex items-center gap-x-1 rounded-md px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2" :class="[ canSendMessage ? 'bg-blue-500 hover:bg-blue-400 focus-visible:outline-blue-500' : 'bg-gray-400 focus-visible:outline-gray-500 cursor-not-allowed']">
|
||||
<span v-if="isSendingMessage">Sending...</span>
|
||||
<span v-else>Send</span>
|
||||
</button>
|
||||
<div class="ml-auto my-auto">
|
||||
<SendMessageButton
|
||||
@send="sendMessage"
|
||||
@delivery-method-changed="this.newMessageDeliveryMethod = $event"
|
||||
:is-sending-message="isSendingMessage"
|
||||
:can-send-message="canSendMessage"
|
||||
:delivery-method="newMessageDeliveryMethod"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -371,10 +375,12 @@ import NotificationUtils from "../../js/NotificationUtils";
|
|||
import WebSocketConnection from "../../js/WebSocketConnection";
|
||||
import AddAudioButton from "./AddAudioButton.vue";
|
||||
import moment from "moment";
|
||||
import SendMessageButton from "./SendMessageButton.vue";
|
||||
|
||||
export default {
|
||||
name: 'ConversationViewer',
|
||||
components: {
|
||||
SendMessageButton,
|
||||
AddAudioButton,
|
||||
},
|
||||
props: {
|
||||
|
|
@ -394,6 +400,7 @@ export default {
|
|||
isLoadingPrevious: false,
|
||||
hasMorePrevious: true,
|
||||
|
||||
newMessageDeliveryMethod: null,
|
||||
newMessageText: "",
|
||||
newMessageImage: null,
|
||||
newMessageImageUrl: null,
|
||||
|
|
@ -1022,6 +1029,7 @@ export default {
|
|||
|
||||
// send message to reticulum
|
||||
const response = await window.axios.post(`/api/v1/lxmf-messages/send`, {
|
||||
"delivery_method": this.newMessageDeliveryMethod,
|
||||
"lxmf_message": {
|
||||
"destination_hash": this.selectedPeer.destination_hash,
|
||||
"content": this.newMessageText,
|
||||
|
|
|
|||
76
src/frontend/components/messages/SendMessageButton.vue
Normal file
76
src/frontend/components/messages/SendMessageButton.vue
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<div class="inline-flex rounded-md shadow-sm">
|
||||
|
||||
<!-- send button -->
|
||||
<button @click="send" :disabled="!canSendMessage" type="button" class="my-auto inline-flex items-center rounded-l-md px-2.5 py-1.5 text-sm font-semibold text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2" :class="[ canSendMessage ? 'bg-blue-500 hover:bg-blue-400 focus-visible:outline-blue-500' : 'bg-gray-400 focus-visible:outline-gray-500 cursor-not-allowed']">
|
||||
<span v-if="isSendingMessage">Sending...</span>
|
||||
<span v-else>
|
||||
<span>Send</span>
|
||||
<span v-if="deliveryMethod === 'direct'"> (Direct Link)</span>
|
||||
<span v-if="deliveryMethod === 'opportunistic'"> (Opportunistic)</span>
|
||||
<span v-if="deliveryMethod === 'propagated'"> (Propagated)</span>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div class="relative">
|
||||
|
||||
<!-- dropdown button -->
|
||||
<button @click="showMenu" :disabled="!canSendMessage" type="button" class="my-auto border-l relative inline-flex items-center rounded-r-md bg-gray-500 focus-visible:outline-gray-400 px-2 py-1.5 text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2" :class="[ canSendMessage ? 'bg-blue-500 hover:bg-blue-400 focus-visible:outline-blue-500' : 'bg-gray-400 focus-visible:outline-gray-500 cursor-not-allowed']">
|
||||
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- dropdown menu -->
|
||||
<Transition
|
||||
enter-active-class="transition ease-out duration-100"
|
||||
enter-from-class="transform opacity-0 scale-95"
|
||||
enter-to-class="transform opacity-100 scale-100"
|
||||
leave-active-class="transition ease-in duration-75"
|
||||
leave-from-class="transform opacity-100 scale-100"
|
||||
leave-to-class="transform opacity-0 scale-95">
|
||||
<div v-if="isShowingMenu" v-click-outside="hideMenu" class="absolute bottom-0 -ml-11 right-0 ml-0 z-10 mb-10 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
||||
<div class="py-1">
|
||||
<button @click="setDeliveryMethod(null)" type="button" class="w-full block text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 whitespace-nowrap border-b">Send Automatically</button>
|
||||
<button @click="setDeliveryMethod('direct')" type="button" class="w-full block text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 whitespace-nowrap">Send over Direct Link</button>
|
||||
<button @click="setDeliveryMethod('opportunistic')" type="button" class="w-full block text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 whitespace-nowrap">Send Opportunistically</button>
|
||||
<button @click="setDeliveryMethod('propagated')" type="button" class="w-full block text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 whitespace-nowrap">Send to Propagation Node</button>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SendMessageButton',
|
||||
props: {
|
||||
deliveryMethod: String,
|
||||
canSendMessage: Boolean,
|
||||
isSendingMessage: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShowingMenu: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
showMenu() {
|
||||
this.isShowingMenu = true;
|
||||
},
|
||||
hideMenu() {
|
||||
this.isShowingMenu = false;
|
||||
},
|
||||
setDeliveryMethod(deliveryMethod) {
|
||||
this.$emit("delivery-method-changed", deliveryMethod);
|
||||
this.hideMenu();
|
||||
},
|
||||
send() {
|
||||
this.$emit("send");
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue