feat: integrate Tauri v2 with Android widget and voice assistant
- Add Tauri v2 shell (Cargo, tauri.conf.json, capabilities, plugins) - Migrate all fetch() calls to apiFetch() for Tauri-aware HTTP - Migrate WebSocket endpoints to resolveEndpoints() for dynamic URLs - Add ServerConfigDialog for remote server URL configuration - Add tauri.ts lib with isTauri detection, apiFetch wrapper, plugin helpers - Add server-config Pinia store with persistence via plugin-store - Conditional PWA (disabled in Tauri builds) - Android: home screen transcript widget (last 5 messages, 30s refresh) - Android: voice command / share activity (SpeechRecognizer + WebSocket) - Android: signed release APK with auto-copy to installers/ - Remove stale frontend/src-tauri directory
This commit is contained in:
@@ -10,19 +10,27 @@ import FloatingTranscriptDebug from './components/FloatingTranscriptDebug.vue'
|
||||
import TerminalFabStack from './components/transcript-debug/TerminalFabStack.vue'
|
||||
import PwaInstallBanner from './components/PwaInstallBanner.vue'
|
||||
import HooksApprovalModal from './components/HooksApprovalModal.vue'
|
||||
import ServerConfigDialog from './components/ServerConfigDialog.vue'
|
||||
import { useGlobalApproval } from './composables/useGlobalApproval'
|
||||
import { initWebMCP, getWebMCP } from './services/webmcp'
|
||||
import { initTorch, destroyTorch } from './services/torch'
|
||||
import { initSessionStateWS, destroySessionStateWS } from './services/session-state-ws'
|
||||
import { endpoints } from './config/endpoints'
|
||||
import { initToolRegistry, activatePageTools, initToolsOnRefresh } from './services/toolRegistry'
|
||||
import { setResponseControls } from './services/tools/handlers/responseHandlers'
|
||||
import { useCanvasStore } from './stores/canvas'
|
||||
import { useProjectCanvasStore } from './stores/projectCanvas'
|
||||
import { useSessionState } from './stores/session-state'
|
||||
import { isTauri } from './lib/tauri'
|
||||
import { useServerConfig } from './stores/server-config'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
// Tauri server config
|
||||
const serverConfig = isTauri ? useServerConfig() : null
|
||||
const showServerConfig = ref(false)
|
||||
const needsServerConfig = computed(() => isTauri && serverConfig && !serverConfig.isConfigured)
|
||||
|
||||
const showVoice = ref(false)
|
||||
const showTranscriptDebug = ref(false)
|
||||
const showDebugConsole = ref(false)
|
||||
@@ -293,6 +301,20 @@ watch(() => route.name, (newPage) => {
|
||||
activatePageTools(newPage as PageName)
|
||||
}
|
||||
})
|
||||
|
||||
// Watch for Tauri server config changes — re-init services when server is configured
|
||||
if (serverConfig) {
|
||||
watch(() => serverConfig!.isConfigured, async (configured) => {
|
||||
if (configured) {
|
||||
showServerConfig.value = false
|
||||
// Re-initialize all services with the new server URL
|
||||
initSessionStateWS()
|
||||
initWhisperSocket()
|
||||
await initWebMCP()
|
||||
await initTorch()
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -325,7 +347,12 @@ watch(() => route.name, (newPage) => {
|
||||
</svg>
|
||||
<span v-if="debugLogs.length" class="log-count">{{ debugLogs.length }}</span>
|
||||
</button>
|
||||
<PwaInstallBanner />
|
||||
<PwaInstallBanner v-if="!isTauri" />
|
||||
<button v-if="isTauri" class="server-config-btn" @click="showServerConfig = true" title="Server settings">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="2" y="2" width="20" height="8" rx="2" ry="2"/><rect x="2" y="14" width="20" height="8" rx="2" ry="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<button
|
||||
@@ -427,6 +454,9 @@ watch(() => route.name, (newPage) => {
|
||||
<!-- Global Hooks Approval Modal -->
|
||||
<HooksApprovalModal />
|
||||
|
||||
<!-- Tauri Server Config Dialog -->
|
||||
<ServerConfigDialog v-if="needsServerConfig || showServerConfig" />
|
||||
|
||||
<!-- Debug Console Panel -->
|
||||
<Teleport to="body">
|
||||
<Transition name="debug-slide">
|
||||
@@ -1031,6 +1061,28 @@ watch(() => route.name, (newPage) => {
|
||||
}
|
||||
}
|
||||
|
||||
/* Server Config Button (Tauri) */
|
||||
.server-config-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 5px;
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
.server-config-btn:hover {
|
||||
background: var(--bg-hover);
|
||||
color: var(--accent, #6366f1);
|
||||
border-color: var(--accent, #6366f1);
|
||||
}
|
||||
|
||||
/* Debug Console Button */
|
||||
.debug-btn {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user