Package Pi Mobile for developer distribution.
Publish the hub as pi-mobile-hub with CLI flags and LAN pairing auth, add mobile deep-link pairing and EAS build config, and expand gitignore for Expo/EAS artifacts. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
saveLastModel,
|
||||
upsertSavedComputer,
|
||||
} from "@/lib/api";
|
||||
import { parseConnectDeepLink } from "@/lib/deeplink";
|
||||
import {
|
||||
createSocket,
|
||||
listModels as requestModels,
|
||||
@@ -38,11 +39,13 @@ import type {
|
||||
ThinkingLevel,
|
||||
} from "@/lib/types";
|
||||
import type { Socket } from "socket.io-client";
|
||||
import * as Linking from "expo-linking";
|
||||
|
||||
type SocketContextValue = {
|
||||
host: string;
|
||||
port: string;
|
||||
computerName: string;
|
||||
token: string;
|
||||
baseUrl: string | null;
|
||||
connected: boolean;
|
||||
connecting: boolean;
|
||||
@@ -56,8 +59,10 @@ type SocketContextValue = {
|
||||
setHost: (host: string) => void;
|
||||
setPort: (port: string) => void;
|
||||
setComputerName: (name: string) => void;
|
||||
setToken: (token: string) => void;
|
||||
connect: () => Promise<boolean>;
|
||||
connectToSavedComputer: (computer: SavedComputer) => Promise<boolean>;
|
||||
connectFromDeepLink: (url: string) => Promise<boolean>;
|
||||
removeSavedComputerEntry: (id: string) => Promise<void>;
|
||||
disconnect: () => void;
|
||||
refreshSessions: () => void;
|
||||
@@ -89,6 +94,7 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
const [host, setHost] = useState("");
|
||||
const [port, setPort] = useState("8787");
|
||||
const [computerName, setComputerName] = useState("");
|
||||
const [token, setToken] = useState("");
|
||||
const [baseUrl, setBaseUrl] = useState<string | null>(null);
|
||||
const [connected, setConnected] = useState(false);
|
||||
const [connecting, setConnecting] = useState(false);
|
||||
@@ -118,6 +124,7 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
setHost(recent.host);
|
||||
setPort(recent.port);
|
||||
setComputerName(recent.name);
|
||||
setToken(recent.token ?? "");
|
||||
void loadSavedProjects(recent.host, recent.port).then(setSavedProjects);
|
||||
});
|
||||
}, []);
|
||||
@@ -168,20 +175,28 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
}, []);
|
||||
|
||||
const connectWithHost = useCallback(
|
||||
async (nextHost: string, nextPort: string, nextName?: string) => {
|
||||
async (
|
||||
nextHost: string,
|
||||
nextPort: string,
|
||||
nextName?: string,
|
||||
nextToken?: string,
|
||||
) => {
|
||||
setConnecting(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const nextBaseUrl = buildBaseUrl(nextHost, nextPort);
|
||||
const healthy = await checkHealth(nextBaseUrl);
|
||||
const trimmedToken = nextToken?.trim();
|
||||
const healthy = await checkHealth(nextBaseUrl, trimmedToken);
|
||||
if (!healthy) {
|
||||
throw new Error("Could not reach Pi Mobile API");
|
||||
}
|
||||
|
||||
disconnect();
|
||||
|
||||
const socket = createSocket(nextBaseUrl, {
|
||||
const socket = createSocket(
|
||||
nextBaseUrl,
|
||||
{
|
||||
onConnect: () => {
|
||||
setConnected(true);
|
||||
setConnecting(false);
|
||||
@@ -215,7 +230,9 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
listener(payload);
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
trimmedToken,
|
||||
);
|
||||
|
||||
socketRef.current = socket;
|
||||
setBaseUrl(nextBaseUrl);
|
||||
@@ -224,12 +241,16 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
if (nextName !== undefined) {
|
||||
setComputerName(nextName);
|
||||
}
|
||||
await saveHostConfig({ host: nextHost, port: nextPort });
|
||||
if (nextToken !== undefined) {
|
||||
setToken(nextToken);
|
||||
}
|
||||
await saveHostConfig({ host: nextHost, port: nextPort, token: trimmedToken });
|
||||
const nextComputers = await upsertSavedComputer(
|
||||
savedComputers,
|
||||
nextHost,
|
||||
nextPort,
|
||||
nextName ?? computerName,
|
||||
trimmedToken,
|
||||
);
|
||||
setSavedComputers(nextComputers);
|
||||
const projects = await loadSavedProjects(nextHost, nextPort);
|
||||
@@ -247,16 +268,58 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
);
|
||||
|
||||
const connect = useCallback(async () => {
|
||||
return connectWithHost(host, port, computerName);
|
||||
}, [connectWithHost, host, port, computerName]);
|
||||
return connectWithHost(host, port, computerName, token);
|
||||
}, [connectWithHost, host, port, computerName, token]);
|
||||
|
||||
const connectToSavedComputer = useCallback(
|
||||
async (computer: SavedComputer) => {
|
||||
return connectWithHost(computer.host, computer.port, computer.name);
|
||||
return connectWithHost(
|
||||
computer.host,
|
||||
computer.port,
|
||||
computer.name,
|
||||
computer.token,
|
||||
);
|
||||
},
|
||||
[connectWithHost],
|
||||
);
|
||||
|
||||
const connectFromDeepLink = useCallback(
|
||||
async (url: string) => {
|
||||
const params = parseConnectDeepLink(url);
|
||||
if (!params) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return connectWithHost(
|
||||
params.host,
|
||||
params.port,
|
||||
params.name ?? params.host,
|
||||
params.token,
|
||||
);
|
||||
},
|
||||
[connectWithHost],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const handleDeepLink = (url: string) => {
|
||||
void connectFromDeepLink(url);
|
||||
};
|
||||
|
||||
void Linking.getInitialURL().then((url) => {
|
||||
if (url) {
|
||||
handleDeepLink(url);
|
||||
}
|
||||
});
|
||||
|
||||
const subscription = Linking.addEventListener("url", (event) => {
|
||||
handleDeepLink(event.url);
|
||||
});
|
||||
|
||||
return () => {
|
||||
subscription.remove();
|
||||
};
|
||||
}, [connectFromDeepLink]);
|
||||
|
||||
const refreshSessions = useCallback(() => {
|
||||
socketRef.current?.emit("sessions:list");
|
||||
}, []);
|
||||
@@ -384,6 +447,7 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
host,
|
||||
port,
|
||||
computerName,
|
||||
token,
|
||||
baseUrl,
|
||||
connected,
|
||||
connecting,
|
||||
@@ -398,8 +462,10 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
setHost,
|
||||
setPort,
|
||||
setComputerName,
|
||||
setToken,
|
||||
connect,
|
||||
connectToSavedComputer,
|
||||
connectFromDeepLink,
|
||||
removeSavedComputerEntry,
|
||||
disconnect,
|
||||
refreshSessions,
|
||||
@@ -419,6 +485,7 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
host,
|
||||
port,
|
||||
computerName,
|
||||
token,
|
||||
baseUrl,
|
||||
connected,
|
||||
connecting,
|
||||
@@ -432,6 +499,7 @@ export function SocketProvider({ children }: { children: ReactNode }) {
|
||||
removeProject,
|
||||
connect,
|
||||
connectToSavedComputer,
|
||||
connectFromDeepLink,
|
||||
removeSavedComputerEntry,
|
||||
disconnect,
|
||||
refreshSessions,
|
||||
|
||||
Reference in New Issue
Block a user