Skip to content

Commit

Permalink
simplify configugration access from renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
jdeniau committed Feb 20, 2024
1 parent 5d6ade5 commit c61fc8d
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 127 deletions.
50 changes: 48 additions & 2 deletions src/Contexts.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createContext, useContext, useState } from 'react';
import { createContext, useContext, useEffect, useState } from 'react';
import { ThemeProvider } from 'styled-components';
import { Configuration } from './configuration/type';
import { DEFAULT_THEME, THEME_LIST } from './theme';

export interface ConnectToFunc {
Expand Down Expand Up @@ -56,9 +57,11 @@ export function ThemeContextProvider({
}: {
children: React.ReactNode;
}): React.ReactElement {
const [themeName, setThemeName] = useState(DEFAULT_THEME.name);
const config = useConfiguration();
const [themeName, setThemeName] = useState(config.theme);

const changeTheme = (newTheme: string) => {
window.config.changeTheme(newTheme);
setThemeName(newTheme);
};

Expand All @@ -70,3 +73,46 @@ export function ThemeContextProvider({
</ThemeProvider>
);
}

const ConfigurationContext = createContext<null | Configuration>(null);

export function ConfigurationContextProvider({
children,
}: {
children: React.ReactNode;
}) {
const [configuration, setConfiguration] = useState<null | Configuration>(
null
);

useEffect(() => {
window.config.getConfiguration().then((c) => {
console.log(c);
setConfiguration(c);
});
}, []);

console.log(configuration);

if (!configuration) {
return null;
}

return (
<ConfigurationContext.Provider value={configuration}>
{children}
</ConfigurationContext.Provider>
);
}

export function useConfiguration(): Configuration {
const value = useContext(ConfigurationContext);

if (!value) {
throw new Error(
'useConfiguration must be used within a ConfigurationContextProvider'
);
}

return value;
}
3 changes: 1 addition & 2 deletions src/component/Connection/ConnectionForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ConnectionContext, ConnectToFunc } from '../../Contexts';
import connections from './SavedConnections';
import { ConnectionObject } from './types';
import { ChangeEvent, FormEvent, PureComponent, useContext } from 'react';

Expand Down Expand Up @@ -53,7 +52,7 @@ class ConnectionForm extends PureComponent<
event.preventDefault();

if (save) {
connections.save(connection.name, connection);
window.config.addConnectionToConfig(connection.name, connection);

Check failure on line 55 in src/component/Connection/ConnectionForm.tsx

View workflow job for this annotation

GitHub Actions / build (18.x)

Expected 1 arguments, but got 2.
}

this.props.connectTo(connection);
Expand Down
23 changes: 3 additions & 20 deletions src/component/Connection/ConnectionPage.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,10 @@
import { Link, Navigate } from 'react-router-dom';
import connections from './SavedConnections';
import { ConnectionObject } from './types';
import { ConnectionContext } from '../../Contexts';
import { useContext, useEffect, useState } from 'react';

function useRegisteredConnectionList(): null | Record<
string,
ConnectionObject
> {
const [registeredConnections, setRegisteredConnections] =
useState<null | Record<string, ConnectionObject>>(null);

useEffect(() => {
connections
.listConnections()
.then((data) => setRegisteredConnections(data ?? {}));
}, []);

return registeredConnections;
}
import { ConnectionContext, useConfiguration } from '../../Contexts';
import { useContext } from 'react';

function ConnectionPage() {
const registeredConnectionList = useRegisteredConnectionList();
const registeredConnectionList = useConfiguration().connections;
const { connectTo } = useContext(ConnectionContext);

if (registeredConnectionList === null) {
Expand Down
37 changes: 0 additions & 37 deletions src/component/Connection/SavedConnections.ts

This file was deleted.

16 changes: 6 additions & 10 deletions src/configuration.test.ts → src/configuration/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { afterEach, describe, expect, test, vi } from 'vitest';
import { existsSync, mkdirSync, readFileSync, writeFile } from 'node:fs';
import envPaths from 'env-paths';
import {
addConnectionToConfig,
readConfigurationFile,
changeTheme,
} from './configuration';
import { addConnectionToConfig, getConfiguration, changeTheme } from '.';

vi.mock('env-paths', () => ({
default: () => ({ config: 'config' }),
Expand Down Expand Up @@ -41,21 +37,21 @@ describe('read configuration from file', () => {
test('empty file', () => {
mockExistsSync.mockReturnValue(false);

expect(readConfigurationFile()).toBe(null);
expect(getConfiguration()).toBe(null);
});

test('existing file but empty', () => {
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue('');

expect(readConfigurationFile()).toBe(null);
expect(getConfiguration()).toBe(null);
});

test('existing file without connexion key', () => {
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue('{}');

expect(readConfigurationFile()).toStrictEqual({
expect(getConfiguration()).toStrictEqual({
connections: {},
});
});
Expand All @@ -64,7 +60,7 @@ describe('read configuration from file', () => {
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue('{ "version": 1, "connections": {}}');

expect(readConfigurationFile()).toStrictEqual({
expect(getConfiguration()).toStrictEqual({
version: 1,
connections: {},
});
Expand Down Expand Up @@ -92,7 +88,7 @@ describe('read configuration from file', () => {
mockExistsSync.mockReturnValue(true);
mockReadFileSync.mockReturnValue(JSON.stringify(config));

expect(readConfigurationFile()).toStrictEqual({
expect(getConfiguration()).toStrictEqual({
version: 1,
connections: {
local: {
Expand Down
42 changes: 16 additions & 26 deletions src/configuration.ts → src/configuration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,19 @@ import { dialog, safeStorage } from 'electron';
import { resolve } from 'node:path';
import { existsSync, mkdirSync, readFileSync, writeFile } from 'node:fs';
import envPaths from 'env-paths';
import { ConnectionObject } from './component/Connection/types';
import { DEFAULT_THEME } from './theme';

export type Configuration = {
version: 1;
theme: string;
connections: Record<string, EncryptedConnectionObject>;
};

type EncryptedConnectionObject = {
password: string;
} & Omit<ConnectionObject, 'password'>;

type EncryptedConfiguration = {
connections: Record<string, EncryptedConnectionObject>;
} & Omit<Configuration, 'connections'>;
import { ConnectionObject } from '../component/Connection/types';
import { DEFAULT_THEME } from '../theme';
import {
Configuration,
EncryptedConnectionObject,
EncryptedConfiguration,
} from './type';

const envPath = envPaths('TianaTables', { suffix: '' });
const dataFilePath = resolve(envPath.config, 'config.json');

console.log('Configuration file path:', dataFilePath);

function getBaseConfig(): Configuration {
return {
version: 1,
Expand Down Expand Up @@ -50,15 +43,15 @@ function decryptConnection(
};
}

export function readConfigurationFile(): null | Configuration {
export function getConfiguration(): Configuration {
if (!existsSync(dataFilePath)) {
return null;
return getBaseConfig();
}

const dataString = readFileSync(dataFilePath, 'utf-8');

if (!dataString) {
return null;
return getBaseConfig();
}

const config = JSON.parse(dataString) as EncryptedConfiguration;
Expand Down Expand Up @@ -98,23 +91,20 @@ function writeConfiguration(config: Configuration): void {
);
}

export function addConnectionToConfig(
name: string,
connection: ConnectionObject
): void {
const config = readConfigurationFile() ?? getBaseConfig();
export function addConnectionToConfig(connection: ConnectionObject): void {
const config = getConfiguration() ?? getBaseConfig();

if (!config.connections) {
config.connections = {};
}

config.connections[name] = connection;
config.connections[connection.name] = connection;

writeConfiguration(config);
}

export function changeTheme(theme: string): void {
const config = readConfigurationFile() ?? getBaseConfig();
const config = getConfiguration() ?? getBaseConfig();
config.theme = theme;

writeConfiguration(config);
Expand Down
15 changes: 15 additions & 0 deletions src/configuration/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ConnectionObject } from '../component/Connection/types';

export type Configuration = {
version: 1;
theme: string;
connections: Record<string, EncryptedConnectionObject>;
};

export type EncryptedConnectionObject = {
password: string;
} & Omit<ConnectionObject, 'password'>;

export type EncryptedConfiguration = {
connections: Record<string, EncryptedConnectionObject>;
} & Omit<Configuration, 'connections'>;
12 changes: 7 additions & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import installExtension, {
} from 'electron-devtools-installer';
import connectionStackInstance from './sql';
import {
readConfigurationFile,
getConfiguration,
addConnectionToConfig,
changeTheme,
} from './configuration';
Expand All @@ -16,6 +16,8 @@ if (require('electron-squirrel-startup')) {
app.quit();
}

const isMac = process.platform !== 'darwin';

const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
Expand Down Expand Up @@ -49,11 +51,11 @@ app.whenReady().then(() => {
.then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log('An error occurred: ', err));

ipcMain.handle('config:read', readConfigurationFile);
ipcMain.handle('config:get', getConfiguration);
ipcMain.handle(
'config:connection:add',
(event: unknown, name: string, connection: ConnectionObject) =>
addConnectionToConfig(name, connection)
(event: unknown, connection: ConnectionObject) =>
addConnectionToConfig(connection)
);
ipcMain.handle('config:theme:change', (event: unknown, name: string) =>
changeTheme(name)
Expand All @@ -71,7 +73,7 @@ app.whenReady().then(() => {
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
if (isMac) {
app.quit();
}
});
Expand Down
15 changes: 6 additions & 9 deletions src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,22 @@

import { Connection } from 'mysql2/promise';
import { ConnectionObject } from './component/Connection/types';
import { Configuration } from './configuration';
import { Configuration } from './configuration/type';
import { contextBridge, ipcRenderer } from 'electron';

// === Configuration ===
interface Config {
readConfigurationFile(): Promise<null | Configuration>;
getConfiguration(): Promise<null | Configuration>;

addConnectionToConfig(
name: string,
connection: ConnectionObject
): Promise<void>;
addConnectionToConfig(connection: ConnectionObject): Promise<void>;

changeTheme(theme: string): void;
}

const config: Config = {
readConfigurationFile: () => ipcRenderer.invoke('config:read'),
addConnectionToConfig: (name: string, connection: ConnectionObject) =>
ipcRenderer.invoke('config:connection:add', name, connection),
getConfiguration: () => ipcRenderer.invoke('config:get'),
addConnectionToConfig: (connection: ConnectionObject) =>
ipcRenderer.invoke('config:connection:add', connection),
changeTheme: (theme: string) =>
ipcRenderer.invoke('config:theme:change', theme),
};
Expand Down
Loading

0 comments on commit c61fc8d

Please sign in to comment.