From e6762ec2b7fc6afe61e49eac5560cb349748a925 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sat, 9 May 2026 19:01:21 -0500 Subject: [PATCH] feat(frontend): update call page and add flood protection settings UI --- meshchatx/src/frontend/components/App.vue | 13 + .../src/frontend/components/call/CallPage.vue | 1446 +++++++++-------- .../components/settings/SettingsPage.vue | 112 ++ meshchatx/src/frontend/locales/en.json | 6 + 4 files changed, 882 insertions(+), 695 deletions(-) diff --git a/meshchatx/src/frontend/components/App.vue b/meshchatx/src/frontend/components/App.vue index 3fc4cfd..26238d0 100644 --- a/meshchatx/src/frontend/components/App.vue +++ b/meshchatx/src/frontend/components/App.vue @@ -251,6 +251,19 @@ + +
  • + + + + +
  • +
  • diff --git a/meshchatx/src/frontend/components/call/CallPage.vue b/meshchatx/src/frontend/components/call/CallPage.vue index 784499f..4110193 100644 --- a/meshchatx/src/frontend/components/call/CallPage.vue +++ b/meshchatx/src/frontend/components/call/CallPage.vue @@ -81,780 +81,836 @@
    +
    -
    -
    - Recording -
    - -
    -
    - -
    - -
    - -
    -
    - -
    -

    - {{ - (activeCall || lastCall)?.remote_identity_name || - initiationTargetName || - $t("call.unknown") - }} -

    -
    - {{ - formatDestinationHash( - (activeCall || lastCall)?.remote_identity_hash || initiationTargetHash - ) - }} -
    -
    - - - {{ activeCall.path_hops }} hops - - - - {{ activeCall.path_interface }} - -
    -
    - - Contact -
    -
    - - -
    -
    - - - - -
    -
    - Duration: {{ callDuration }} -
    - - -
    - -
    -
    - - -
    -
    - - -
    - - - - - -
    -
    -
    - - -
    -
    - - - - - -
    - - - +
    +

    LXST is disabled

    +

    + Telephony is currently disabled. Enable it to make and receive calls. +

    +
    -
    -
    -
    -
    - +
    diff --git a/meshchatx/src/frontend/components/settings/SettingsPage.vue b/meshchatx/src/frontend/components/settings/SettingsPage.vue index 1892447..c9d824e 100644 --- a/meshchatx/src/frontend/components/settings/SettingsPage.vue +++ b/meshchatx/src/frontend/components/settings/SettingsPage.vue @@ -2257,6 +2257,71 @@ {{ $t("app.inbound_stamp_description") }}
    +
    +
    +
    + {{ $t("app.flood_protection") }} +
    +
    + {{ $t("app.flood_protection_description") }} +
    + +
    +
    +
    + {{ $t("app.flood_threshold") }} +
    + +
    +
    +
    + {{ $t("app.flood_max_stamp_cost") }} +
    + +
    +
    +
    + {{ $t("app.flood_cooldown") }} +
    + +
    +
    +
    @@ -2936,6 +3001,12 @@ export default { "app.inbound_stamp_description", "app.inbound_stamps_required_title", "app.inbound_stamps_required_description", + "app.flood_protection", + "app.flood_protection_description", + "app.flood_protection_enabled", + "app.flood_threshold", + "app.flood_max_stamp_cost", + "app.flood_cooldown", ], propagation: [ "LXMF", @@ -3609,6 +3680,47 @@ export default { ); }, 1000); }, + async onLxmfFloodProtectionEnabledChange(value) { + await this.updateConfig({ + lxmf_flood_protection_enabled: value, + }); + }, + async onLxmfFloodThresholdChange() { + if (this.saveTimeouts.flood_threshold) clearTimeout(this.saveTimeouts.flood_threshold); + this.saveTimeouts.flood_threshold = setTimeout(async () => { + let v = Number(this.config.lxmf_flood_threshold_per_minute); + if (!v || v < 1) v = 30; + else if (v > 1000) v = 1000; + this.config.lxmf_flood_threshold_per_minute = v; + await this.updateConfig({ + lxmf_flood_threshold_per_minute: v, + }); + }, 1000); + }, + async onLxmfFloodMaxStampCostChange() { + if (this.saveTimeouts.flood_max_cost) clearTimeout(this.saveTimeouts.flood_max_cost); + this.saveTimeouts.flood_max_cost = setTimeout(async () => { + let v = Number(this.config.lxmf_flood_max_stamp_cost); + if (!v || v < 1) v = 24; + else if (v > 254) v = 254; + this.config.lxmf_flood_max_stamp_cost = v; + await this.updateConfig({ + lxmf_flood_max_stamp_cost: v, + }); + }, 1000); + }, + async onLxmfFloodCooldownChange() { + if (this.saveTimeouts.flood_cooldown) clearTimeout(this.saveTimeouts.flood_cooldown); + this.saveTimeouts.flood_cooldown = setTimeout(async () => { + let v = Number(this.config.lxmf_flood_cooldown_seconds); + if (!v || v < 30) v = 30; + else if (v > 3600) v = 3600; + this.config.lxmf_flood_cooldown_seconds = v; + await this.updateConfig({ + lxmf_flood_cooldown_seconds: v, + }); + }, 1000); + }, async onPageArchiverEnabledChangeWrapper(value) { this.config.page_archiver_enabled = value; await this.updateConfig( diff --git a/meshchatx/src/frontend/locales/en.json b/meshchatx/src/frontend/locales/en.json index ceca817..504b020 100644 --- a/meshchatx/src/frontend/locales/en.json +++ b/meshchatx/src/frontend/locales/en.json @@ -146,6 +146,12 @@ "inbound_stamps_required_description": "When off, direct messages to you do not require proof-of-work stamps. When on, set the stamp cost below. Higher values mean more work for senders.", "inbound_stamp_cost": "Inbound Message Stamp Cost", "inbound_stamp_description": "Proof-of-work difficulty for direct messages. Range: 1-254. Default: 8.", + "flood_protection": "Flood Protection", + "flood_protection_description": "Automatically raise the inbound stamp cost when receiving too many messages per minute from many sources. This makes coordinated spam attacks computationally expensive while keeping normal conversations affordable.", + "flood_protection_enabled": "Enable auto-adjusting stamp cost", + "flood_threshold": "Messages per minute threshold", + "flood_max_stamp_cost": "Maximum stamp cost during flood", + "flood_cooldown": "Cooldown before lowering cost (seconds)", "local_message_auto_delete_title": "Delete old messages on this device", "local_message_auto_delete_description": "Removes messages from the local database after the age you set. This only affects this device and no data is deleted from the network.", "local_message_auto_delete_age": "Delete messages older than",