mirror of
https://github.com/YuzuZensai/Discord-Presence-Relay.git
synced 2026-09-13 10:49:02 +00:00
✨ feat: Implement waiting state
This commit is contained in:
+7
-3
@@ -150,15 +150,19 @@ function updateTrayMenu(status: RelayStatus): void {
|
||||
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: status.running ? 'Relay: Running' : 'Relay: Stopped',
|
||||
label: status.running
|
||||
? 'Relay: Running'
|
||||
: status.waiting
|
||||
? 'Relay: Waiting for Discord…'
|
||||
: 'Relay: Stopped',
|
||||
enabled: false
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: status.running ? 'Stop Relay' : 'Start Relay',
|
||||
label: status.running || status.waiting ? 'Stop Relay' : 'Start Relay',
|
||||
click: async () => {
|
||||
try {
|
||||
if (status.running) {
|
||||
if (status.running || status.waiting) {
|
||||
await relay.stop()
|
||||
} else {
|
||||
await relay.start()
|
||||
|
||||
+39
-4
@@ -7,6 +7,7 @@ import { platform, type ClaimedSocket, type ProcessInfo } from './platform'
|
||||
|
||||
const MAX_SOCKETS = 10
|
||||
const DISCOVERY_INTERVAL_MS = 3000
|
||||
const WAITING_RETRY_INTERVAL_MS = 3000
|
||||
|
||||
interface AppAsset {
|
||||
id: string
|
||||
@@ -101,6 +102,7 @@ export interface LastActivity {
|
||||
|
||||
export interface RelayStatus {
|
||||
running: boolean
|
||||
waiting: boolean
|
||||
unsupported: boolean
|
||||
instances: RelayInstance[]
|
||||
connectedClients: ConnectedClient[]
|
||||
@@ -120,8 +122,10 @@ export class RpcRelay extends EventEmitter {
|
||||
private connectedClients = new Map<number, ConnectedClient>()
|
||||
private nextClientId = 1
|
||||
private discoveryTimer: NodeJS.Timeout | null = null
|
||||
private waitingTimer: NodeJS.Timeout | null = null
|
||||
private lastActivity: LastActivity | null = null
|
||||
private running = false
|
||||
private waiting = false
|
||||
private lastError: string | null = null
|
||||
private restarting = false
|
||||
private mirrors = new Map<number, MirrorConnection>()
|
||||
@@ -138,6 +142,7 @@ export class RpcRelay extends EventEmitter {
|
||||
|
||||
return {
|
||||
running: this.running,
|
||||
waiting: this.waiting,
|
||||
unsupported: !platform.isSupported,
|
||||
instances,
|
||||
connectedClients: [...this.connectedClients.values()],
|
||||
@@ -181,11 +186,13 @@ export class RpcRelay extends EventEmitter {
|
||||
this.claimed = platform.discoverAndClaim()
|
||||
|
||||
if (this.claimed.length === 0) {
|
||||
this.lastError = 'No running Discord clients found (no discord-ipc-N sockets)'
|
||||
this.emitStatus()
|
||||
throw new Error(this.lastError)
|
||||
this.waitForDiscord()
|
||||
return
|
||||
}
|
||||
|
||||
this.waiting = false
|
||||
this.stopWaitingTimer()
|
||||
|
||||
const fake = platform.fakeSocketPath()
|
||||
platform.removeFakeSocket(fake)
|
||||
|
||||
@@ -211,7 +218,13 @@ export class RpcRelay extends EventEmitter {
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
if (!this.running) return
|
||||
this.stopWaitingTimer()
|
||||
this.waiting = false
|
||||
|
||||
if (!this.running) {
|
||||
this.emitStatus()
|
||||
return
|
||||
}
|
||||
this.running = false
|
||||
this.stopDiscoveryTimer()
|
||||
|
||||
@@ -236,6 +249,28 @@ export class RpcRelay extends EventEmitter {
|
||||
return this.claimed[0]?.index
|
||||
}
|
||||
|
||||
private waitForDiscord(): void {
|
||||
this.waiting = true
|
||||
this.lastError = null
|
||||
this.emitStatus()
|
||||
|
||||
if (this.waitingTimer) return
|
||||
this.waitingTimer = setInterval(() => {
|
||||
if (!this.waiting) return
|
||||
void this.start().catch((err) => {
|
||||
this.lastError = err instanceof Error ? err.message : String(err)
|
||||
this.emitStatus()
|
||||
})
|
||||
}, WAITING_RETRY_INTERVAL_MS)
|
||||
}
|
||||
|
||||
private stopWaitingTimer(): void {
|
||||
if (this.waitingTimer) {
|
||||
clearInterval(this.waitingTimer)
|
||||
this.waitingTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
private startDiscoveryTimer(): void {
|
||||
this.stopDiscoveryTimer()
|
||||
this.discoveryTimer = setInterval(() => this.discoverNewInstances(), DISCOVERY_INTERVAL_MS)
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Button, LinkButton } from './components/Button'
|
||||
|
||||
const EMPTY_STATUS: RelayStatus = {
|
||||
running: false,
|
||||
waiting: false,
|
||||
unsupported: false,
|
||||
instances: [],
|
||||
connectedClients: [],
|
||||
@@ -120,7 +121,7 @@ export function App(): React.JSX.Element {
|
||||
const toggleRelay = async (): Promise<void> => {
|
||||
setLoading(true)
|
||||
try {
|
||||
if (status.running) {
|
||||
if (status.running || status.waiting) {
|
||||
await window.api.stop()
|
||||
} else {
|
||||
await window.api.start()
|
||||
@@ -227,11 +228,23 @@ export function App(): React.JSX.Element {
|
||||
<section className="rounded-xl bg-zinc-800/60 border border-zinc-700 p-4 flex items-center justify-between">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm">Relay</span>
|
||||
<span className={`text-xs ${status.running ? 'text-emerald-400' : 'text-zinc-500'}`}>
|
||||
{status.running ? 'Running' : 'Stopped'}
|
||||
<span
|
||||
className={`text-xs ${
|
||||
status.running
|
||||
? 'text-emerald-400'
|
||||
: status.waiting
|
||||
? 'text-amber-400'
|
||||
: 'text-zinc-500'
|
||||
}`}
|
||||
>
|
||||
{status.running ? 'Running' : status.waiting ? 'Waiting for Discord…' : 'Stopped'}
|
||||
</span>
|
||||
</div>
|
||||
<Toggle checked={status.running} onChange={() => toggleRelay()} disabled={loading} />
|
||||
<Toggle
|
||||
checked={status.running || status.waiting}
|
||||
onChange={() => toggleRelay()}
|
||||
disabled={loading}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section className="rounded-xl bg-zinc-800/60 border border-zinc-700 p-4 flex flex-col gap-2">
|
||||
|
||||
Reference in New Issue
Block a user