Show WebSocket status on UI
This commit is contained in:
parent
a249919061
commit
1a05e184a7
6 changed files with 71 additions and 28 deletions
|
|
@ -222,7 +222,7 @@ export class SyncSettingsTab extends PluginSettingTab {
|
|||
.addButton((button) =>
|
||||
button.setButtonText("Test connection").onClick(async () => {
|
||||
new Notice(
|
||||
(await this.syncClient.checkConnection()).message
|
||||
(await this.syncClient.checkConnection()).serverMessage
|
||||
);
|
||||
await this.statusDescription.updateConnectionState();
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@ import "./status-description.scss";
|
|||
|
||||
import type {
|
||||
HistoryStats,
|
||||
CheckConnectionResult,
|
||||
NetworkConnectionStatus,
|
||||
SyncClient
|
||||
} from "sync-client";
|
||||
|
||||
export class StatusDescription {
|
||||
private lastHistoryStats: HistoryStats | undefined;
|
||||
private lastRemaining: number | undefined;
|
||||
private lastConnectionState: CheckConnectionResult | undefined;
|
||||
private lastConnectionState: NetworkConnectionStatus | undefined;
|
||||
|
||||
private statusChangeListeners: (() => void)[] = [];
|
||||
|
||||
|
|
@ -28,9 +28,13 @@ export class StatusDescription {
|
|||
}
|
||||
);
|
||||
|
||||
this.syncClient.addOnSettingsChangeListener(() => {
|
||||
void this.updateConnectionState();
|
||||
});
|
||||
this.syncClient.addWebSocketStatusChangeListener(
|
||||
() => void this.updateConnectionState()
|
||||
);
|
||||
|
||||
this.syncClient.addOnSettingsChangeListener(
|
||||
() => void this.updateConnectionState()
|
||||
);
|
||||
}
|
||||
|
||||
public async updateConnectionState(): Promise<void> {
|
||||
|
|
@ -61,7 +65,15 @@ export class StatusDescription {
|
|||
|
||||
if (!this.lastConnectionState.isSuccessful) {
|
||||
container.createSpan({
|
||||
text: `VaultLink failed to connect to the remote server with the error "${this.lastConnectionState.message}"`,
|
||||
text: `VaultLink failed to connect to the remote server with error '${this.lastConnectionState.serverMessage}'`,
|
||||
cls: "error"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.lastConnectionState.isWebSocketConnected) {
|
||||
container.createSpan({
|
||||
text: `${this.lastConnectionState.serverMessage} but the WebSocket connection could not be established.`,
|
||||
cls: "error"
|
||||
});
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ export {
|
|||
type HistoryEntry
|
||||
} from "./tracing/sync-history";
|
||||
export { Logger, LogLevel, LogLine } from "./tracing/logger";
|
||||
export type { CheckConnectionResult } from "./services/sync-service";
|
||||
export { type SyncSettings } from "./persistence/settings";
|
||||
export type { RelativePath, StoredDatabase } from "./persistence/database";
|
||||
export type { FileSystemOperations } from "./file-operations/filesystem-operations";
|
||||
export type { PersistenceProvider } from "./persistence/persistence";
|
||||
|
||||
export type { NetworkConnectionStatus } from "./sync-client";
|
||||
export { SyncClient } from "./sync-client";
|
||||
|
|
|
|||
|
|
@ -307,13 +307,13 @@ export class SyncService {
|
|||
if (result.isAuthenticated) {
|
||||
return {
|
||||
isSuccessful: true,
|
||||
message: `Successfully connected to server (version: ${result.serverVersion}) and authenticated.`
|
||||
message: `Successfully connected to server (version: ${result.serverVersion}) and authenticated`
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
isSuccessful: false,
|
||||
message: `Successfully connected to server (version: ${result.serverVersion}) but failed to authenticate.`
|
||||
message: `Successfully connected to server (version: ${result.serverVersion}) but failed to authenticate`
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import type { RelativePath, StoredDatabase } from "./persistence/database";
|
|||
import { Database } from "./persistence/database";
|
||||
import type { SyncSettings } from "./persistence/settings";
|
||||
import { Settings } from "./persistence/settings";
|
||||
import type { CheckConnectionResult } from "./services/sync-service";
|
||||
import { SyncService } from "./services/sync-service";
|
||||
import { Syncer } from "./sync-operations/syncer";
|
||||
import type { FileSystemOperations } from "./file-operations/filesystem-operations";
|
||||
|
|
@ -16,6 +15,12 @@ import { FileOperations } from "./file-operations/file-operations";
|
|||
import { ConnectionStatus } from "./services/connection-status";
|
||||
import { UnrestrictedSyncer } from "./sync-operations/unrestricted-syncer";
|
||||
|
||||
export interface NetworkConnectionStatus {
|
||||
isSuccessful: boolean;
|
||||
serverMessage: string;
|
||||
isWebSocketConnected: boolean;
|
||||
}
|
||||
|
||||
export class SyncClient {
|
||||
// eslint-disable-next-line @typescript-eslint/max-params
|
||||
private constructor(
|
||||
|
|
@ -134,8 +139,13 @@ export class SyncClient {
|
|||
return client;
|
||||
}
|
||||
|
||||
public async checkConnection(): Promise<CheckConnectionResult> {
|
||||
return this.syncService.checkConnection();
|
||||
public async checkConnection(): Promise<NetworkConnectionStatus> {
|
||||
const server = await this.syncService.checkConnection();
|
||||
return {
|
||||
isSuccessful: server.isSuccessful,
|
||||
serverMessage: server.message,
|
||||
isWebSocketConnected: this.syncer.isWebSocketConnected
|
||||
};
|
||||
}
|
||||
|
||||
public getHistoryEntries(): readonly HistoryEntry[] {
|
||||
|
|
@ -202,6 +212,10 @@ export class SyncClient {
|
|||
this.syncer.addRemainingOperationsListener(listener);
|
||||
}
|
||||
|
||||
public addWebSocketStatusChangeListener(listener: () => void): void {
|
||||
this.syncer.addWebSocketStatusChangeListener(listener);
|
||||
}
|
||||
|
||||
public async syncLocallyCreatedFile(
|
||||
relativePath: RelativePath
|
||||
): Promise<void> {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export class Syncer {
|
|||
private readonly remainingOperationsListeners: ((
|
||||
remainingOperations: number
|
||||
) => void)[] = [];
|
||||
private readonly webSocketStatusChangeListeners: (() => void)[] = [];
|
||||
private readonly syncQueue: PQueue;
|
||||
|
||||
private runningScheduleSyncForOfflineChanges: Promise<void> | undefined;
|
||||
|
|
@ -70,15 +71,8 @@ export class Syncer {
|
|||
this.setWebSocketRefreshInterval();
|
||||
}
|
||||
|
||||
public async reset(): Promise<void> {
|
||||
await this.waitUntilFinished();
|
||||
this.setWebSocketRefreshInterval();
|
||||
this.updateWebSocket(this.settings.getSettings());
|
||||
}
|
||||
|
||||
public stop(): void {
|
||||
clearInterval(this.refreshApplyRemoteChangesWebSocketInterval);
|
||||
this.applyRemoteChangesWebSocket?.close();
|
||||
public get isWebSocketConnected(): boolean {
|
||||
return this.applyRemoteChangesWebSocket?.readyState === WebSocket.OPEN;
|
||||
}
|
||||
|
||||
public addRemainingOperationsListener(
|
||||
|
|
@ -87,6 +81,10 @@ export class Syncer {
|
|||
this.remainingOperationsListeners.push(listener);
|
||||
}
|
||||
|
||||
public addWebSocketStatusChangeListener(listener: () => void): void {
|
||||
this.webSocketStatusChangeListeners.push(listener);
|
||||
}
|
||||
|
||||
public async syncLocallyCreatedFile(
|
||||
relativePath: RelativePath
|
||||
): Promise<void> {
|
||||
|
|
@ -245,6 +243,17 @@ export class Syncer {
|
|||
return this.syncQueue.onEmpty();
|
||||
}
|
||||
|
||||
public async reset(): Promise<void> {
|
||||
await this.waitUntilFinished();
|
||||
this.setWebSocketRefreshInterval();
|
||||
this.updateWebSocket(this.settings.getSettings());
|
||||
}
|
||||
|
||||
public stop(): void {
|
||||
clearInterval(this.refreshApplyRemoteChangesWebSocketInterval);
|
||||
this.applyRemoteChangesWebSocket?.close();
|
||||
}
|
||||
|
||||
private updateWebSocket(settings: SyncSettings): void {
|
||||
this.applyRemoteChangesWebSocket?.close();
|
||||
|
||||
|
|
@ -277,14 +286,22 @@ export class Syncer {
|
|||
}
|
||||
);
|
||||
|
||||
this.applyRemoteChangesWebSocket.onerror = (event): void => {
|
||||
console.error(event);
|
||||
this.logger.error(`WebSocket error`);
|
||||
// The JS WebSocket API doesn't support setting headers, so we have to send the token as a message
|
||||
this.applyRemoteChangesWebSocket.onopen = (): void => {
|
||||
this.applyRemoteChangesWebSocket?.send(settings.token);
|
||||
this.webSocketStatusChangeListeners.forEach((listener) => {
|
||||
listener();
|
||||
});
|
||||
};
|
||||
|
||||
// The JS WebSocket API doesn't support setting headers, so we have to send the token as a message
|
||||
this.applyRemoteChangesWebSocket.onopen = (): void =>
|
||||
this.applyRemoteChangesWebSocket?.send(settings.token);
|
||||
this.applyRemoteChangesWebSocket.onclose = (event): void => {
|
||||
this.logger.error(
|
||||
`WebSocket closed with code ${event.code}: ${event.reason}`
|
||||
);
|
||||
this.webSocketStatusChangeListeners.forEach((listener) => {
|
||||
listener();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private setWebSocketRefreshInterval(): void {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue