💄 style(desktop): improve WelcomeStep layout centering in onboarding (#13125)

* 💄 style(desktop): improve WelcomeStep layout centering in onboarding

Made-with: Cursor

* 🐛 fix(desktop): validate remote server URL in isRemoteServerConfigured

Made-with: Cursor
This commit is contained in:
Innei
2026-03-19 21:18:41 +08:00
committed by GitHub
parent 8d387a98a0
commit 0f67a5b8d7
3 changed files with 57 additions and 7 deletions

View File

@@ -93,10 +93,26 @@ export default class RemoteServerConfigCtr extends ControllerModule {
*/
async isRemoteServerConfigured(config?: DataSyncConfig): Promise<boolean> {
const effectiveConfig = config ?? (await this.getRemoteServerConfig());
return (
effectiveConfig.active &&
(effectiveConfig.storageMode !== 'selfHost' || !!effectiveConfig.remoteServerUrl)
);
const isActive = Boolean(effectiveConfig.active);
const isSelfHostConfigured =
effectiveConfig.storageMode !== 'selfHost' ||
this.isValidSelfHostRemoteUrl(effectiveConfig.remoteServerUrl);
return isActive && isSelfHostConfigured;
}
private isValidSelfHostRemoteUrl(remoteServerUrl?: string): boolean {
if (!remoteServerUrl) return false;
const normalizedUrl = remoteServerUrl.trim();
if (!normalizedUrl) return false;
try {
const parsedUrl = new URL(normalizedUrl);
return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:';
} catch {
return false;
}
}
/**
@@ -537,7 +553,7 @@ export default class RemoteServerConfigCtr extends ControllerModule {
}
async getRemoteServerUrl(config?: DataSyncConfig) {
const dataConfig = this.normalizeConfig(config ? config : await this.getRemoteServerConfig());
const dataConfig = this.normalizeConfig(config ?? (await this.getRemoteServerConfig()));
return dataConfig.storageMode === 'cloud' ? OFFICIAL_CLOUD_SERVER : dataConfig.remoteServerUrl;
}

View File

@@ -747,6 +747,16 @@ describe('RemoteServerConfigCtr', () => {
});
describe('isRemoteServerConfigured', () => {
it('should return false when active is undefined', async () => {
mockStoreManager.get.mockReturnValue({
storageMode: 'cloud',
});
const result = await controller.isRemoteServerConfigured();
expect(result).toBe(false);
});
it('should return true for active cloud mode (no remoteServerUrl needed)', async () => {
mockStoreManager.get.mockReturnValue({
active: true,
@@ -794,6 +804,30 @@ describe('RemoteServerConfigCtr', () => {
expect(result).toBe(false);
});
it('should return false for selfHost mode with blank remoteServerUrl', async () => {
mockStoreManager.get.mockReturnValue({
active: true,
remoteServerUrl: ' ',
storageMode: 'selfHost',
});
const result = await controller.isRemoteServerConfigured();
expect(result).toBe(false);
});
it('should return false for selfHost mode with invalid remoteServerUrl', async () => {
mockStoreManager.get.mockReturnValue({
active: true,
remoteServerUrl: 'foo',
storageMode: 'selfHost',
});
const result = await controller.isRemoteServerConfigured();
expect(result).toBe(false);
});
it('should use provided config instead of fetching', async () => {
// Store has inactive config
mockStoreManager.get.mockReturnValue({