add ability to enable/disable telephone

This commit is contained in:
liamcottle 2025-11-24 21:24:10 +13:00
commit a366e8ff39
2 changed files with 101 additions and 12 deletions

View file

@ -153,10 +153,10 @@ class ReticulumMeshChat:
self.audio_call_manager = AudioCallManager(identity=self.identity)
self.audio_call_manager.register_incoming_call_callback(self.on_incoming_audio_call)
# init telephone
# todo check if user wants to enable telephone
# init telephone if enabled
self.telephone = None
self.init_telephone()
if self.config.telephone_enabled.get():
self.init_telephone()
# start background thread for auto announce loop
thread = threading.Thread(target=asyncio.run, args=(self.announce_loop(),))
@ -175,6 +175,32 @@ class ReticulumMeshChat:
self.telephone.set_established_callback(self.on_telephone_call_established)
self.telephone.set_ended_callback(self.on_telephone_call_ended)
# enable telephone
def enable_telephone(self):
# mark as enabled in config
self.config.telephone_enabled.set(True)
# do nothing if already enabled
if self.telephone is not None:
return
# start instance
self.init_telephone()
# disable telephone
def disable_telephone(self):
# teardown telephone instance
if self.telephone is not None:
AsyncUtils.run_async(asyncio.to_thread(self.telephone.teardown))
# mark as disabled in config
self.config.telephone_enabled.set(False)
# clear instance
self.telephone = None
# handle receiving a new telephone call
def on_telephone_ringing(self, caller_identity: RNS.Identity):
print("on_telephone_ringing: {}".format(caller_identity.hash.hex()))
@ -344,6 +370,22 @@ class ReticulumMeshChat:
"status": "ok",
})
# enable telephone
@routes.get("/api/v1/telephone/enable")
async def index(request):
self.enable_telephone()
return web.json_response({
"message": "Telephone has been enabled.",
})
# disable telephone
@routes.get("/api/v1/telephone/disable")
async def index(request):
self.disable_telephone()
return web.json_response({
"message": "Telephone has been disabled.",
})
# serve telephone status
@routes.get("/api/v1/telephone/status")
async def index(request):
@ -351,8 +393,9 @@ class ReticulumMeshChat:
# make sure telephone is enabled
if self.telephone is None:
return web.json_response({
"enabled": False,
"message": "Telephone is disabled",
}, status=503)
})
# get active call info
active_call = None
@ -381,6 +424,7 @@ class ReticulumMeshChat:
}
return web.json_response({
"enabled": True,
"is_busy": self.telephone.busy,
"call_status": self.telephone.call_status,
"active_call": active_call,
@ -412,6 +456,12 @@ class ReticulumMeshChat:
@routes.get("/api/v1/telephone/call/{identity_hash}")
async def index(request):
# make sure telephone enabled
if self.telephone is None:
return web.json_response({
"message": "Telephone has been disabled.",
}, status=503)
# get path params
identity_hash_hex = request.match_info.get("identity_hash", "")
timeout_seconds = int(request.query.get("timeout", 15))
@ -3653,6 +3703,7 @@ class Config:
lxmf_user_icon_name = StringConfig("lxmf_user_icon_name", None)
lxmf_user_icon_foreground_colour = StringConfig("lxmf_user_icon_foreground_colour", None)
lxmf_user_icon_background_colour = StringConfig("lxmf_user_icon_background_colour", None)
telephone_enabled = BoolConfig("telephone_enabled", True)
# FIXME: we should probably set this as an instance variable of ReticulumMeshChat so it has a proper home, and pass it in to the constructor?
nomadnet_cached_links = {}

View file

@ -247,12 +247,16 @@
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 0 1-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z" />
</svg>
</div>
<div class="my-auto dark:text-white">Calls</div>
<div class="ml-auto">
<a @click.stop href="../call.html" target="_blank" class="my-auto inline-flex items-center gap-x-1 rounded-md bg-gray-500 px-2 py-1 text-sm font-semibold text-white shadow-sm hover:bg-gray-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500
dark:bg-zinc-800 dark:text-white dark:hover:bg-zinc-700 dark:focus-visible:outline-zinc-500
">
<span>Open Phone</span>
<div class="my-auto dark:text-white">Phone</div>
<div class="ml-auto space-x-1">
<button v-if="telephoneEnabled" @click.stop="disableTelephone" type="button" class="my-auto inline-flex items-center gap-x-1 rounded-md bg-gray-500 px-2 py-1 text-sm font-semibold text-white shadow-sm hover:bg-gray-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500 dark:bg-zinc-800 dark:text-white dark:hover:bg-zinc-700 dark:focus-visible:outline-zinc-500">
<span>Disable</span>
</button>
<button v-if="!telephoneEnabled" @click.stop="enableTelephone" type="button" class="my-auto inline-flex items-center gap-x-1 rounded-md bg-gray-500 px-2 py-1 text-sm font-semibold text-white shadow-sm hover:bg-gray-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500 dark:bg-zinc-800 dark:text-white dark:hover:bg-zinc-700 dark:focus-visible:outline-zinc-500">
<span>Enable</span>
</button>
<a @click.stop href="../call.html" target="_blank" class="my-auto inline-flex items-center gap-x-1 rounded-md bg-gray-500 px-2 py-1 text-sm font-semibold text-white shadow-sm hover:bg-gray-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500 dark:bg-zinc-800 dark:text-white dark:hover:bg-zinc-700 dark:focus-visible:outline-zinc-500">
<span>Open</span>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5">
<path fill-rule="evenodd" d="M4.25 5.5a.75.75 0 0 0-.75.75v8.5c0 .414.336.75.75.75h8.5a.75.75 0 0 0 .75-.75v-4a.75.75 0 0 1 1.5 0v4A2.25 2.25 0 0 1 12.75 17h-8.5A2.25 2.25 0 0 1 2 14.75v-8.5A2.25 2.25 0 0 1 4.25 4h5a.75.75 0 0 1 0 1.5h-5Z" clip-rule="evenodd" />
<path fill-rule="evenodd" d="M6.194 12.753a.75.75 0 0 0 1.06.053L16.5 4.44v2.81a.75.75 0 0 0 1.5 0v-4.5a.75.75 0 0 0-.75-.75h-4.5a.75.75 0 0 0 0 1.5h2.553l-9.056 8.194a.75.75 0 0 0-.053 1.06Z" clip-rule="evenodd" />
@ -261,7 +265,13 @@ dark:bg-zinc-800 dark:text-white dark:hover:bg-zinc-700 dark:focus-visible:outli
</div>
</div>
<div v-if="isShowingCallsSection" class="divide-y text-gray-900 border-t border-gray-300 dark:border-zinc-900">
<div class="p-1 flex dark:border-zinc-900 dark:text-white">
<div v-if="!telephoneEnabled" class="p-1 flex dark:border-zinc-900 dark:text-white">
<div>
<div>Status</div>
<div class="text-sm">Disabled</div>
</div>
</div>
<div v-if="telephoneEnabled" class="p-1 flex dark:border-zinc-900 dark:text-white">
<div>
<div>
<span v-if="activeCall && activeCall.status === 6">Active Call</span>
@ -277,7 +287,7 @@ dark:bg-zinc-800 dark:text-white dark:hover:bg-zinc-700 dark:focus-visible:outli
<span v-else>Unknown Caller</span>
</span>
</div>
<div v-else>Hung up, waiting for call...</div>
<div v-else>Available. Waiting for call...</div>
</div>
</div>
<div v-if="activeCall" class="ml-auto my-auto mr-1 space-x-2">
@ -342,6 +352,7 @@ export default {
config: null,
appInfo: null,
telephoneEnabled: false,
activeCall: null,
propagationNodeStatus: null,
@ -540,6 +551,7 @@ export default {
const response = await axios.get("/api/v1/telephone/status");
// update ui
this.telephoneEnabled = response.data.enabled;
this.activeCall = response.data.active_call;
} catch(e) {
@ -572,6 +584,32 @@ export default {
// ignore error hanging up call
}
},
async enableTelephone() {
try {
// enable telephone
await axios.get(`/api/v1/telephone/enable`);
// update ui
await this.getTelephoneStatus();
} catch(e) {
// ignore error
}
},
async disableTelephone() {
try {
// disable telephone
await axios.get(`/api/v1/telephone/disable`);
// update ui
await this.getTelephoneStatus();
} catch(e) {
// ignore error
}
},
onAppNameClick() {
// user may be on mobile, and is unable to scroll back to sidebar, so let them tap app name to do it
this.$refs["middle"].scrollTo({