fixed auto download
This commit is contained in:
parent
867b03aa1e
commit
fbdd4274ac
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -125,7 +125,30 @@ const ChatScreen: React.FC = () => {
|
|||
isInitialLoad.current = false;
|
||||
}
|
||||
};
|
||||
loadMessages();
|
||||
loadMessages().then(async () => {
|
||||
// Auto-Re-Download: fehlende Anhänge vom Server nachladen (wenn aktiviert)
|
||||
const autoDownload = await AsyncStorage.getItem('aria_auto_download');
|
||||
if (autoDownload === 'false') return;
|
||||
setTimeout(() => {
|
||||
setMessages(prev => {
|
||||
const missing: {id: string, serverPath: string}[] = [];
|
||||
for (const msg of prev) {
|
||||
for (const att of msg.attachments || []) {
|
||||
if (att.serverPath && !att.uri) {
|
||||
missing.push({ id: msg.id, serverPath: att.serverPath });
|
||||
}
|
||||
}
|
||||
}
|
||||
if (missing.length > 0) {
|
||||
console.log(`[Chat] ${missing.length} fehlende Anhaenge — lade nach...`);
|
||||
for (const m of missing) {
|
||||
rvs.send('file_request' as any, { serverPath: m.serverPath, requestId: m.id });
|
||||
}
|
||||
}
|
||||
return prev;
|
||||
});
|
||||
}, 2000); // Warten bis RVS verbunden ist
|
||||
});
|
||||
}, []);
|
||||
|
||||
// RVS-Nachrichten abonnieren
|
||||
|
|
@ -165,20 +188,23 @@ const ChatScreen: React.FC = () => {
|
|||
return;
|
||||
}
|
||||
|
||||
// STT-Ergebnis: Transkribierten Text unter den Placeholder schreiben
|
||||
if (message.type === 'stt_result') {
|
||||
if (message.type === 'chat') {
|
||||
const sender = (message.payload.sender as string) || '';
|
||||
|
||||
// STT-Ergebnis: Transkribierten Text in die Sprach-Bubble schreiben
|
||||
if (sender === 'stt') {
|
||||
const sttText = (message.payload.text as string) || '';
|
||||
if (sttText) {
|
||||
setMessages(prev => prev.map(m =>
|
||||
m.sender === 'user' && m.text.includes('Spracheingabe wird verarbeitet')
|
||||
? { ...m, text: sttText ? `\uD83C\uDFA4 ${sttText}` : '\uD83C\uDFA4 (nicht erkannt)' }
|
||||
? { ...m, text: `\uD83C\uDFA4 ${sttText}` }
|
||||
: m
|
||||
));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === 'chat') {
|
||||
// Nur Nachrichten von ARIA anzeigen — eigene Nachrichten werden lokal hinzugefuegt
|
||||
const sender = (message.payload.sender as string) || '';
|
||||
// Eigene Nachrichten ignorieren (werden lokal hinzugefuegt)
|
||||
if (sender === 'user' || sender === 'diagnostic') return;
|
||||
|
||||
const text = (message.payload.text as string) || '';
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ const SettingsScreen: React.FC = () => {
|
|||
const [events, setEvents] = useState<EventEntry[]>([]);
|
||||
const [connLog, setConnLog] = useState<ConnectionLogEntry[]>(rvs.getConnectionLog());
|
||||
const [storagePath, setStoragePath] = useState(DEFAULT_STORAGE_PATH);
|
||||
const [autoDownload, setAutoDownload] = useState(true);
|
||||
const [storageSize, setStorageSize] = useState('...');
|
||||
const [editingPath, setEditingPath] = useState(false);
|
||||
const [tempPath, setTempPath] = useState('');
|
||||
|
|
@ -83,10 +84,13 @@ const SettingsScreen: React.FC = () => {
|
|||
setManualPort(String(config.port));
|
||||
setManualToken(config.token);
|
||||
}
|
||||
// Speicherpfad laden
|
||||
// Speicherpfad + Auto-Download laden
|
||||
AsyncStorage.getItem(STORAGE_PATH_KEY).then(saved => {
|
||||
if (saved) setStoragePath(saved);
|
||||
});
|
||||
AsyncStorage.getItem('aria_auto_download').then(saved => {
|
||||
if (saved !== null) setAutoDownload(saved === 'true');
|
||||
});
|
||||
}, []);
|
||||
|
||||
// Speichergroesse berechnen
|
||||
|
|
@ -441,10 +445,29 @@ const SettingsScreen: React.FC = () => {
|
|||
{/* === Speicher === */}
|
||||
<Text style={styles.sectionTitle}>Anhang-Speicher</Text>
|
||||
<View style={styles.card}>
|
||||
<View style={styles.toggleRow}>
|
||||
<View style={styles.toggleInfo}>
|
||||
<Text style={styles.toggleLabel}>Auto-Download</Text>
|
||||
<Text style={styles.toggleHint}>
|
||||
Fehlende Anhaenge beim App-Start automatisch vom Server laden
|
||||
</Text>
|
||||
</View>
|
||||
<Switch
|
||||
value={autoDownload}
|
||||
onValueChange={(val) => {
|
||||
setAutoDownload(val);
|
||||
AsyncStorage.setItem('aria_auto_download', String(val));
|
||||
}}
|
||||
trackColor={{ false: '#2A2A3E', true: '#0096FF' }}
|
||||
thumbColor={autoDownload ? '#FFFFFF' : '#666680'}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={{height: 16}} />
|
||||
<Text style={styles.toggleLabel}>Lokaler Speicherort</Text>
|
||||
<Text style={styles.toggleHint}>
|
||||
Hier werden Bilder und Dateien aus dem Chat gespeichert.
|
||||
Bei geloeschtem Cache werden Anhaenge automatisch ueber RVS neu geladen.
|
||||
{autoDownload ? ' Fehlende Dateien werden automatisch nachgeladen.' : ' Fehlende Dateien koennen per Tippen geladen werden.'}
|
||||
</Text>
|
||||
|
||||
{editingPath ? (
|
||||
|
|
|
|||
|
|
@ -925,7 +925,10 @@ class ARIABridge:
|
|||
payload = message.get("payload", {})
|
||||
|
||||
if msg_type == "chat":
|
||||
# Text von der App → an aria-core
|
||||
# Nur User-Nachrichten weiterleiten — ARIA/Diagnostic-Antworten ignorieren (sonst Loop!)
|
||||
sender = payload.get("sender", "")
|
||||
if sender in ("aria", "diagnostic", "stt"):
|
||||
return
|
||||
text = payload.get("text", "")
|
||||
if text:
|
||||
logger.info("[rvs] App-Chat: '%s'", text[:80])
|
||||
|
|
@ -1104,34 +1107,23 @@ class ARIABridge:
|
|||
|
||||
if text.strip():
|
||||
logger.info("[rvs] STT Ergebnis: '%s'", text[:80])
|
||||
# STT-Ergebnis zurueck an die App senden (zur Anzeige, nicht nochmal verarbeiten)
|
||||
# ERST an aria-core senden (wichtigster Schritt)
|
||||
await self.send_to_core(text, source="app-voice")
|
||||
# STT-Text an RVS senden (fuer Anzeige in App + Diagnostic)
|
||||
# sender="stt" damit Bridge es ignoriert (kein Loop)
|
||||
try:
|
||||
await self._send_to_rvs({
|
||||
"type": "stt_result",
|
||||
"type": "chat",
|
||||
"payload": {
|
||||
"text": text,
|
||||
"sender": "user",
|
||||
"sender": "stt",
|
||||
},
|
||||
"timestamp": int(asyncio.get_event_loop().time() * 1000),
|
||||
})
|
||||
except Exception as e:
|
||||
logger.warning("[rvs] STT-Ergebnis konnte nicht an App gesendet werden: %s", e)
|
||||
# Text trotzdem an aria-core senden
|
||||
await self.send_to_core(text, source="app-voice")
|
||||
logger.warning("[rvs] STT-Text konnte nicht an RVS gesendet werden: %s", e)
|
||||
else:
|
||||
logger.info("[rvs] Keine Sprache erkannt — ignoriert")
|
||||
try:
|
||||
await self._send_to_rvs({
|
||||
"type": "stt_result",
|
||||
"payload": {
|
||||
"text": "",
|
||||
"error": "Keine Sprache erkannt",
|
||||
"sender": "user",
|
||||
},
|
||||
"timestamp": int(asyncio.get_event_loop().time() * 1000),
|
||||
})
|
||||
except Exception as e:
|
||||
logger.warning("[rvs] STT-Fehler konnte nicht an App gesendet werden: %s", e)
|
||||
|
||||
except Exception:
|
||||
logger.exception("[rvs] Audio-Verarbeitung fehlgeschlagen")
|
||||
|
|
|
|||
|
|
@ -196,7 +196,10 @@
|
|||
<!-- Chat Test -->
|
||||
<div class="grid">
|
||||
<div class="card full">
|
||||
<h2>Chat Test</h2>
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;">
|
||||
<h2 style="margin:0;">Chat Test</h2>
|
||||
<button class="btn secondary" onclick="toggleChatFullscreen()" id="btn-chat-fs" style="padding:4px 10px;font-size:11px;">Vollbild</button>
|
||||
</div>
|
||||
<div class="chat-box" id="chat-box"></div>
|
||||
<div class="input-row">
|
||||
<input type="text" id="chat-input" placeholder="Nachricht an ARIA...">
|
||||
|
|
@ -206,6 +209,20 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chat Vollbild Modal -->
|
||||
<div id="chat-fullscreen" style="display:none;position:fixed;top:0;left:0;width:100vw;height:100vh;background:#0D0D1A;z-index:1000;padding:16px;flex-direction:column;">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;">
|
||||
<h2 style="margin:0;color:#0096FF;">ARIA Chat</h2>
|
||||
<button class="btn secondary" onclick="toggleChatFullscreen()" style="padding:6px 14px;">Schliessen</button>
|
||||
</div>
|
||||
<div id="chat-box-fs" class="chat-box" style="flex:1;max-height:none;min-height:0;overflow-y:auto;"></div>
|
||||
<div class="input-row" style="margin-top:8px;">
|
||||
<input type="text" id="chat-input-fs" placeholder="Nachricht an ARIA..." onkeydown="if(event.key==='Enter'){testGatewayFS();event.preventDefault();}">
|
||||
<button class="btn" onclick="testGatewayFS()">Gateway senden</button>
|
||||
<button class="btn" onclick="testRVSFS()">Via RVS senden</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Session + Brain Viewer -->
|
||||
<div class="grid" style="grid-template-columns: 1fr 1fr;">
|
||||
<div class="card">
|
||||
|
|
@ -503,7 +520,8 @@
|
|||
const p = msg.msg.payload || {};
|
||||
const sender = p.sender || '?';
|
||||
const chatType = (sender === 'aria') ? 'received' : 'sent';
|
||||
addChat(chatType, p.text || '?', `via RVS (${sender})`);
|
||||
const label = sender === 'stt' ? '\uD83C\uDFA4 Spracheingabe' : `via RVS (${sender})`;
|
||||
addChat(chatType, p.text || '?', label);
|
||||
return;
|
||||
}
|
||||
if (msg.type === 'proxy_result') {
|
||||
|
|
@ -856,18 +874,59 @@
|
|||
}
|
||||
|
||||
function addChat(type, text, meta) {
|
||||
const el = document.createElement('div');
|
||||
el.className = `chat-msg ${type}`;
|
||||
const escaped = escapeHtml(text);
|
||||
let linked = linkifyText(escaped);
|
||||
// /shared/uploads/ Pfade als Inline-Bilder anzeigen
|
||||
linked = linked.replace(/\/shared\/uploads\/[^\s<"]+\.(jpg|jpeg|png|gif)/gi, (match) => {
|
||||
return `<a href="${match}" target="_blank">${match}</a><img src="${match}" class="chat-media" onclick="openLightbox('image','${match}')" onerror="this.style.display='none'">`;
|
||||
});
|
||||
el.innerHTML = `${linked}<div class="meta">${escapeHtml(meta)} — ${new Date().toLocaleTimeString('de-DE')}</div>`;
|
||||
chatBox.appendChild(el);
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
const html = `${linked}<div class="meta">${escapeHtml(meta)} — ${new Date().toLocaleTimeString('de-DE')}</div>`;
|
||||
// In beide Chat-Boxen schreiben (normal + Vollbild)
|
||||
for (const box of [chatBox, document.getElementById('chat-box-fs')]) {
|
||||
if (!box) continue;
|
||||
const el = document.createElement('div');
|
||||
el.className = `chat-msg ${type}`;
|
||||
el.innerHTML = html;
|
||||
box.appendChild(el);
|
||||
box.scrollTop = box.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
let chatFullscreen = false;
|
||||
function toggleChatFullscreen() {
|
||||
const modal = document.getElementById('chat-fullscreen');
|
||||
chatFullscreen = !chatFullscreen;
|
||||
if (chatFullscreen) {
|
||||
modal.style.display = 'flex';
|
||||
// Chat-Inhalt synchronisieren
|
||||
const fsBox = document.getElementById('chat-box-fs');
|
||||
fsBox.innerHTML = chatBox.innerHTML;
|
||||
fsBox.scrollTop = fsBox.scrollHeight;
|
||||
document.getElementById('chat-input-fs').focus();
|
||||
} else {
|
||||
modal.style.display = 'none';
|
||||
}
|
||||
}
|
||||
function testGatewayFS() {
|
||||
const input = document.getElementById('chat-input-fs');
|
||||
const text = input.value.trim();
|
||||
if (!text) return;
|
||||
addChat('sent', text, 'Gateway direkt');
|
||||
send({ action: 'test_gateway', text });
|
||||
input.value = '';
|
||||
}
|
||||
function testRVSFS() {
|
||||
const input = document.getElementById('chat-input-fs');
|
||||
const text = input.value.trim();
|
||||
if (!text) return;
|
||||
addChat('sent', text, 'via RVS');
|
||||
send({ action: 'test_rvs', text });
|
||||
input.value = '';
|
||||
}
|
||||
// Escape schliesst Vollbild-Chat
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && chatFullscreen) toggleChatFullscreen();
|
||||
});
|
||||
|
||||
function openLightbox(mediaType, url) {
|
||||
const lb = document.getElementById('lightbox');
|
||||
|
|
|
|||
|
|
@ -462,11 +462,6 @@ function connectRVS(forcePlain) {
|
|||
pipelineEnd(true, `Antwort via RVS von ${sender}: "${(msg.payload.text || "").slice(0, 120)}"`);
|
||||
}
|
||||
broadcast({ type: "rvs_chat", msg });
|
||||
} else if (msg.type === "stt_result" && msg.payload) {
|
||||
const text = msg.payload.text || "(nicht erkannt)";
|
||||
log("info", "rvs", `STT: "${text.slice(0, 100)}"`);
|
||||
// Im Chat als User-Nachricht anzeigen (zur Info, wurde schon an ARIA gesendet)
|
||||
broadcast({ type: "rvs_chat", msg: { type: "chat", payload: { text: `\uD83C\uDFA4 ${text}`, sender: "user" } } });
|
||||
} else if (msg.type === "heartbeat") {
|
||||
// ignorieren
|
||||
} else {
|
||||
|
|
|
|||
36
release.sh
36
release.sh
|
|
@ -51,8 +51,30 @@ fi
|
|||
echo -e " ${GREEN}✓${NC} Login erfolgreich"
|
||||
echo ""
|
||||
|
||||
# ── Versionsnummern aktualisieren ─────────────
|
||||
echo -e "${GREEN}[1/5] Versionsnummern auf $VERSION setzen...${NC}"
|
||||
|
||||
# package.json
|
||||
sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$VERSION\"/" android/package.json
|
||||
echo -e " ${GREEN}✓${NC} package.json → $VERSION"
|
||||
|
||||
# build.gradle: versionName + versionCode (aus Major.Minor.Patch berechnen)
|
||||
MAJOR=$(echo "$VERSION" | cut -d. -f1)
|
||||
MINOR=$(echo "$VERSION" | cut -d. -f2)
|
||||
PATCH=$(echo "$VERSION" | cut -d. -f3)
|
||||
VERSION_CODE=$((MAJOR * 10000 + MINOR * 100 + PATCH))
|
||||
sed -i "s/versionName \"[^\"]*\"/versionName \"$VERSION\"/" android/android/app/build.gradle
|
||||
sed -i "s/versionCode [0-9]*/versionCode $VERSION_CODE/" android/android/app/build.gradle
|
||||
echo -e " ${GREEN}✓${NC} build.gradle → versionName $VERSION, versionCode $VERSION_CODE"
|
||||
|
||||
# SettingsScreen: Anzeige-Version
|
||||
sed -i "s/Version [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]* [^<]*/Version $VERSION /" android/src/screens/SettingsScreen.tsx
|
||||
echo -e " ${GREEN}✓${NC} SettingsScreen → Version $VERSION"
|
||||
|
||||
echo ""
|
||||
|
||||
# ── APK bauen ─────────────────────────────────
|
||||
echo -e "${GREEN}[1/4] APK bauen...${NC}"
|
||||
echo -e "${GREEN}[2/5] APK bauen...${NC}"
|
||||
cd android
|
||||
./build.sh release
|
||||
cd ..
|
||||
|
|
@ -70,7 +92,11 @@ echo -e " ${GREEN}✓${NC} APK gebaut ($APK_SIZE)"
|
|||
echo ""
|
||||
|
||||
# ── Git Tag ───────────────────────────────────
|
||||
echo -e "${GREEN}[2/4] Git Tag $TAG...${NC}"
|
||||
echo -e "${GREEN}[3/5] Git Tag $TAG...${NC}"
|
||||
|
||||
# Versions-Aenderungen committen
|
||||
git add android/package.json android/android/app/build.gradle android/src/screens/SettingsScreen.tsx
|
||||
git commit -m "release: bump version to $VERSION" 2>/dev/null || echo -e " ${YELLOW}Keine Aenderungen zum Committen${NC}"
|
||||
|
||||
if git rev-parse "$TAG" &>/dev/null; then
|
||||
echo -e " ${YELLOW}Tag $TAG existiert bereits — überspringe${NC}"
|
||||
|
|
@ -79,7 +105,7 @@ else
|
|||
echo -e " ${GREEN}✓${NC} Tag $TAG erstellt"
|
||||
fi
|
||||
|
||||
git push origin "$TAG"
|
||||
git push origin main "$TAG"
|
||||
echo -e " ${GREEN}✓${NC} Tag gepusht"
|
||||
echo ""
|
||||
|
||||
|
|
@ -102,7 +128,7 @@ fi
|
|||
RELEASE_BODY_ESCAPED=$(printf '%s' "$RELEASE_BODY" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))' 2>/dev/null || printf '"%s"' "$RELEASE_BODY" | sed 's/"/\\"/g')
|
||||
|
||||
# ── Gitea Release erstellen ───────────────────
|
||||
echo -e "${GREEN}[3/4] Gitea Release erstellen...${NC}"
|
||||
echo -e "${GREEN}[4/5] Gitea Release erstellen...${NC}"
|
||||
|
||||
RELEASE_RESPONSE=$(curl -s -X POST \
|
||||
"$GITEA_URL/api/v1/repos/$GITEA_REPO/releases" \
|
||||
|
|
@ -127,7 +153,7 @@ echo -e " ${GREEN}✓${NC} Release #$RELEASE_ID erstellt"
|
|||
echo ""
|
||||
|
||||
# ── APK hochladen ─────────────────────────────
|
||||
echo -e "${GREEN}[4/4] APK hochladen...${NC}"
|
||||
echo -e "${GREEN}[5/5] APK hochladen...${NC}"
|
||||
|
||||
UPLOAD_RESPONSE=$(curl -s -X POST \
|
||||
"$GITEA_URL/api/v1/repos/$GITEA_REPO/releases/$RELEASE_ID/assets?name=$APK_NAME" \
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ const MAX_SESSIONS = parseInt(process.env.MAX_SESSIONS || "10", 10);
|
|||
// Erlaubte Nachrichtentypen — alles andere wird verworfen
|
||||
const ALLOWED_TYPES = new Set([
|
||||
"chat", "audio", "file", "location", "mode", "log", "event", "heartbeat",
|
||||
"file_request", "file_response", "file_saved", "stt_result",
|
||||
]);
|
||||
|
||||
// Token-Raum: token -> { clients: Set<ws> }
|
||||
|
|
|
|||
Loading…
Reference in New Issue