force user to wait 1 second before sending another message

This commit is contained in:
liamcottle
2025-02-13 16:56:46 +13:00
parent bfebaa8a90
commit c753b03479
4 changed files with 38 additions and 23 deletions

View File

@@ -75,7 +75,6 @@
<!-- text input -->
<textarea
:readonly="isSendingMessage"
v-model="newMessageText"
@keydown.enter.exact.native="onEnterPressed"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
@@ -101,6 +100,7 @@ import Connection from "../../js/Connection.js";
import MessageUtils from "../../js/MessageUtils.js";
import DeviceUtils from "../../js/DeviceUtils.js";
import TimeUtils from "../../js/TimeUtils.js";
import Utils from "../../js/Utils.js";
export default {
name: 'MessageViewer',
@@ -140,6 +140,11 @@ export default {
return false;
}
// can't send if already sending
if(this.isSendingMessage){
return;
}
// do nothing if message is empty
const newMessageText = this.newMessageText;
if(newMessageText == null || newMessageText === ""){
@@ -147,7 +152,6 @@ export default {
}
// todo validate message max length
// todo rate limit to 1 message per second, otherwise duplicate messages in same second have same packet hash and won't send/ack
// show loading
this.isSendingMessage = true;
@@ -165,6 +169,9 @@ export default {
alert("failed to send message");
}
// force user to wait 1 second before sending another message
await Utils.sleep(1000);
// hide loading
this.isSendingMessage = false;

View File

@@ -175,13 +175,8 @@ class Connection {
// send message
const message = await GlobalState.connection.sendTextMessage(publicKey, text);
// mark message as failed after estimated timeout
setTimeout(async () => {
await Database.Message.setMessageFailedByAckCode(message.expectedAckCrc, "timeout");
}, message.estTimeout);
// save to database
await Database.Message.insert({
const databaseMessage = await Database.Message.insert({
status: "sending",
to: publicKey,
from: GlobalState.selfInfo.publicKey,
@@ -195,6 +190,11 @@ class Connection {
error: null,
});
// mark message as failed after estimated timeout
setTimeout(async () => {
await Database.Message.setMessageFailedById(databaseMessage.id, "timeout");
}, message.estTimeout);
}
static async syncMessages() {

View File

@@ -107,6 +107,21 @@ class Message {
});
}
static async getMessageById(id) {
return await database.messages.findOne({
selector: {
id: {
$eq: id,
},
},
sort: [
{
timestamp: "desc",
},
],
}).exec();
}
// mark a message as delivered by its ack code
static async setMessageDeliveredByAckCode(ackCode) {
@@ -133,30 +148,19 @@ class Message {
}
// mark a message as failed by its ack code
static async setMessageFailedByAckCode(ackCode, reason) {
static async setMessageFailedById(id, reason) {
// find one latest message by ack code
// this will prevent updating older messages that might have the same ack code
const message = await database.messages.findOne({
selector: {
expected_ack_crc: {
$eq: ackCode,
},
},
sort: [
{
timestamp: "desc",
},
],
}).exec();
const message = await this.getMessageById(id);
// do nothing if message not found
if(!message){
return;
}
// do nothing if already delivered
if(message.status === "delivered"){
// only update if still in sending state
if(message.status !== "sending"){
return;
}

View File

@@ -1,5 +1,9 @@
class Utils {
static async sleep(millis) {
return await new Promise((resolve, reject) => setTimeout(resolve, millis));
}
static bytesToHex(uint8Array) {
return Array.from(uint8Array).map(byte => byte.toString(16).padStart(2, '0')).join('');
}