Compare commits
No commits in common. "main" and "dial-failed-handling" have entirely different histories.
main
...
dial-faile
|
|
@ -33,38 +33,8 @@ export const LogsPage = ({ service, logs }: LogsPageProps) => (
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<pre id="logs" style="margin-top: 1rem; max-height: 70vh; overflow-y: auto;">
|
<pre style="margin-top: 1rem;">
|
||||||
<code>{logs.trim()}</code>
|
<code>{logs.trim()}</code>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<script dangerouslySetInnerHTML={{ __html: `
|
|
||||||
(function() {
|
|
||||||
const logsEl = document.getElementById('logs');
|
|
||||||
const codeEl = logsEl.querySelector('code');
|
|
||||||
let userScrolledUp = false;
|
|
||||||
|
|
||||||
logsEl.addEventListener('scroll', () => {
|
|
||||||
const atBottom = logsEl.scrollTop + logsEl.clientHeight >= logsEl.scrollHeight - 50;
|
|
||||||
userScrolledUp = !atBottom;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Scroll to bottom initially
|
|
||||||
logsEl.scrollTop = logsEl.scrollHeight;
|
|
||||||
|
|
||||||
const service = new URLSearchParams(location.search).get('service') || 'phone-ap';
|
|
||||||
const es = new EventSource('/logs/stream?service=' + encodeURIComponent(service));
|
|
||||||
|
|
||||||
es.onmessage = (e) => {
|
|
||||||
codeEl.textContent += '\\n' + e.data;
|
|
||||||
if (!userScrolledUp) {
|
|
||||||
logsEl.scrollTop = logsEl.scrollHeight;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
es.onerror = () => {
|
|
||||||
console.error('SSE connection lost, reconnecting...');
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
`}} />
|
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { Hono } from "hono"
|
import { Hono } from "hono"
|
||||||
import { streamSSE } from "hono/streaming"
|
|
||||||
import { join } from "node:path"
|
import { join } from "node:path"
|
||||||
import { $ } from "bun"
|
import { $ } from "bun"
|
||||||
import { IndexPage } from "./components/IndexPage"
|
import { IndexPage } from "./components/IndexPage"
|
||||||
|
|
@ -56,36 +55,6 @@ app.get("/logs", async (c) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// SSE endpoint for live log streaming
|
|
||||||
app.get("/logs/stream", async (c) => {
|
|
||||||
const service = c.req.query("service") || "phone"
|
|
||||||
const validServices = ["phone-ap", "phone-web", "phone"]
|
|
||||||
const selectedService = validServices.includes(service) ? service : "phone"
|
|
||||||
|
|
||||||
return streamSSE(c, async (stream) => {
|
|
||||||
const proc = Bun.spawn(
|
|
||||||
["journalctl", "-u", `${selectedService}.service`, "-f", "-n", "0", "--no-pager", "--no-hostname"],
|
|
||||||
{ stdout: "pipe" }
|
|
||||||
)
|
|
||||||
|
|
||||||
const reader = proc.stdout.getReader()
|
|
||||||
const decoder = new TextDecoder()
|
|
||||||
|
|
||||||
try {
|
|
||||||
while (true) {
|
|
||||||
const { done, value } = await reader.read()
|
|
||||||
if (done) break
|
|
||||||
const text = decoder.decode(value)
|
|
||||||
for (const line of text.split("\n").filter(Boolean)) {
|
|
||||||
await stream.writeSSE({ data: line })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
proc.kill()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Handle WiFi configuration submission
|
// Handle WiFi configuration submission
|
||||||
app.post("/save", async (c) => {
|
app.post("/save", async (c) => {
|
||||||
const formData = await c.req.parseBody()
|
const formData = await c.req.parseBody()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user