Skip to content

Commit

Permalink
Replace craco with vite
Browse files Browse the repository at this point in the history
  • Loading branch information
GermanBluefox committed Sep 20, 2024
1 parent 1528f5f commit 65a2a84
Show file tree
Hide file tree
Showing 37 changed files with 726 additions and 470 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ Here is an example of how to add Reolink E1:
To add a new camera, you must create a Pull Request on GitHub with the following changes:
- Add new file into `cameras` folder. This is a backend to read the single image from the camera.
- Add GUI file in the `src/src/Types/` folder. This is the configuration dialog for the camera
- Add this dialog in `src/src/Tabs/Cameras.js` file analogical as other cameras are added. Only two lines should be added:
- Add this dialog in `src/src/Tabs/Cameras.tsx` file analogical as other cameras are added. Only two lines should be added:
- Import new configuration dialog like `import RTSPMyCamConfig from '../Types/RTSPMyCam';`
- Extend `TYPES` structure with the new camera like `mycam: { Config: RTSPMyCamConfig, name: 'MyCam' },`
The attribute name must be the same as the name of the file in the `cameras` folder.
Expand Down
1 change: 0 additions & 1 deletion src-widgets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
"private": true,
"version": "2.1.2",
"dependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@craco/craco": "^7.1.0",
"@iobroker/adapter-react-v5": "^7.1.4",
"@iobroker/vis-2-widgets-react-dev": "^4.0.3",
Expand Down
13 changes: 11 additions & 2 deletions src-widgets/src/SnapshotCamera.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import React from 'react';
import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
} from '@mui/material';

import { Close } from '@mui/icons-material';

Expand Down Expand Up @@ -354,7 +360,10 @@ class SnapshotCamera extends Generic {
left: 0,
}}
>
<div style={{ color: 'red' }}>{Generic.t('Cannot load URL')}:</div>
<div style={{ color: 'red' }}>
{Generic.t('Cannot load URL')}
:
</div>
<div>{this.getUrl(true)}</div>
</div>
) : null}
Expand Down
24 changes: 24 additions & 0 deletions src/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import config, { reactConfig } from '@iobroker/eslint-config';

// disable temporary the rule 'jsdoc/require-param' and enable 'jsdoc/require-jsdoc'
config.forEach(rule => {
if (rule?.plugins?.jsdoc) {
rule.rules['jsdoc/require-jsdoc'] = 'off';
rule.rules['jsdoc/require-param'] = 'off';
}
});

export default [
...config,
...reactConfig,
{
languageOptions: {
parserOptions: {
projectService: {
allowDefaultProject: ['*.js', '*.mjs'],
},
tsconfigRootDir: import.meta.dirname,
},
},
},
];
48 changes: 48 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link
rel="shortcut icon"
href="public/favicon.ico"
/>
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta
name="theme-color"
content="#000000"
/>
<link
rel="manifest"
href="public/manifest.json"
/>
<script>
const script = document.createElement('script');
window.registerSocketOnLoad = function (cb) {
window.socketLoadedHandler = cb;
};
script.onload = function () {
typeof window.socketLoadedHandler === 'function' && window.socketLoadedHandler();
};
setTimeout(() => {
script.src =
window.location.port === '3000'
? window.location.protocol + '//' + window.location.hostname + ':8081/lib/js/socket.io.js'
: '%PUBLIC_URL%/../../lib/js/socket.io.js';
}, 1000);

document.head.appendChild(script);
</script>
<title>ioBroker.cameras</title>
<script
type="module"
src="/src/index.tsx"
></script>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
24 changes: 13 additions & 11 deletions src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,27 @@
"version": "2.1.2",
"private": true,
"dependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@iobroker/adapter-react-v5": "^7.1.4",
"@material-ui/icons": "^4.11.3",
"@iobroker/eslint-config": "^0.1.6",
"@iobroker/types": "^6.0.11",
"@mui/icons-material": "^6.1.1",
"@mui/material": "^6.1.1",
"babel-eslint": "^10.1.0",
"@types/react": "^18.3.7",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
"react-scripts": "^5.0.1",
"eslint": "^8.56.0",
"eslint-plugin-import": "^2.29.1"
"typescript": "^5.6.2",
"vite": "^5.4.6",
"vite-tsconfig-paths": "^5.0.1"
},
"scripts": {
"start": "set DANGEROUSLY_DISABLE_HOST_CHECK=true&& react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"lint": "eslint -c eslint.config.mjs src"
"start": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"lint": "eslint -c eslint.config.mjs src",
"tsc": "tsc -p tsconfig.json src"
},
"eslintConfig": {
"extends": "react-app"
Expand Down
3 changes: 3 additions & 0 deletions src/prettier.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import prettierConfig from '@iobroker/eslint-config/prettier.config.mjs';

export default prettierConfig;
Binary file added src/public/cameras.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 0 additions & 30 deletions src/public/index.html

This file was deleted.

116 changes: 67 additions & 49 deletions src/src/App.js → src/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,40 @@
import React from 'react';
import React, { type JSX } from 'react';
import { ThemeProvider, StyledEngineProvider } from '@mui/material/styles';

import { AppBar, Tabs, Tab } from '@mui/material';
import { AppBar, Tabs, Tab, type Theme } from '@mui/material';

import { Loader, I18n, GenericApp } from '@iobroker/adapter-react-v5';
import {
Loader,
I18n,
GenericApp,
type GenericAppState,
type GenericAppProps,
type GenericAppSettings,
} from '@iobroker/adapter-react-v5';

import TabOptions from './Tabs/Options';
import TabCameras from './Tabs/Cameras';

import langEn from './i18n/en';
import langDe from './i18n/de';
import langRu from './i18n/ru';
import langPt from './i18n/pt';
import langNl from './i18n/nl';
import langFr from './i18n/fr';
import langIt from './i18n/it';
import langEs from './i18n/es';
import langPl from './i18n/pl';
import langUk from './i18n/uk';
import langZhCn from './i18n/zh-cn';
import langEn from './i18n/en.json';
import langDe from './i18n/de.json';
import langRu from './i18n/ru.json';
import langPt from './i18n/pt.json';
import langNl from './i18n/nl.json';
import langFr from './i18n/fr.json';
import langIt from './i18n/it.json';
import langEs from './i18n/es.json';
import langPl from './i18n/pl.json';
import langUk from './i18n/uk.json';
import langZhCn from './i18n/zh-cn.json';
import type { CamerasInstanceNative } from '@/types';

function inIframe(): boolean {
try {
return window.self !== window.top;
} catch {
return true;
}
}

const styles = {
tabContent: {
Expand All @@ -31,17 +47,25 @@ const styles = {
height: 'calc(100% - 64px - 48px - 20px - 38px)',
overflow: 'auto',
},
selected: theme => ({
selected: (theme: Theme) => ({
color: theme.palette.mode === 'dark' ? undefined : '#FFF !important',
}),
indicator: theme => ({
indicator: (theme: Theme) => ({
backgroundColor: theme.palette.mode === 'dark' ? theme.palette.secondary.main : '#FFF',
}),
};

class App extends GenericApp {
constructor(props) {
const extendedProps = {};
interface AppState extends GenericAppState {
alive: boolean;
isIFrame: boolean;
}

class App extends GenericApp<GenericAppProps, AppState> {
private subscribed: string = '';
private readonly isIFrame: boolean = inIframe();

constructor(props: GenericAppProps) {
const extendedProps: GenericAppSettings = {};
extendedProps.adapterName = 'cameras';
extendedProps.doNotLoadAllObjects = true;
extendedProps.translations = {
Expand Down Expand Up @@ -69,20 +93,20 @@ class App extends GenericApp {
super(props, extendedProps);
}

onAliveChanged = (id, state) => {
onAliveChanged = (id: string, state: ioBroker.State | null | undefined): void => {
if (id && this.state.alive !== !!state?.val) {
this.setState({ alive: !!state?.val });
}
};

componentWillUnmount() {
componentWillUnmount(): void {
this.subscribed && this.socket.unsubscribeState(this.subscribed, this.onAliveChanged);
super.componentWillUnmount();
}

// called when connected with admin and loaded instance object
onConnectionReady() {
this.socket.getState(`${this.instanceId}.alive`).then(state => {
onConnectionReady(): void {
void this.socket.getState(`${this.instanceId}.alive`).then(state => {
if (this.state.alive !== !!state?.val) {
this.setState({ alive: !!state?.val });
}
Expand All @@ -94,22 +118,11 @@ class App extends GenericApp {
);
}
this.subscribed = `${this.instanceId}.alive`;
this.socket.subscribeState(this.subscribed, this.onAliveChanged);
return this.socket.subscribeState(this.subscribed, this.onAliveChanged);
});
}

getSelectedTab() {
const tab = this.state.selectedTab;

if (!tab || tab === 'options') {
return 0;
}
if (tab === 'cameras') {
return 1;
}
}

render() {
render(): JSX.Element {
if (!this.state.loaded) {
return (
<StyledEngineProvider injectFirst>
Expand All @@ -129,19 +142,19 @@ class App extends GenericApp {
>
<AppBar position="static">
<Tabs
value={this.getSelectedTab()}
onChange={(e, index) => this.selectTab(e.target.dataset.name, index)}
value={this.state.selectedTab}
onChange={(_e, selectedTab: string): void => this.setState({ selectedTab })}
sx={{ '& .MuiTabs-indicator': styles.indicator }}
>
<Tab
value="options"
sx={{ '&.Mui-selected': styles.selected }}
selected={this.state.selectedTab === 'options'}
label={I18n.t('Options')}
data-name="options"
/>
<Tab
value="cameras"
sx={{ '&.Mui-selected': styles.selected }}
selected={this.state.selectedTab === 'cameras'}
label={I18n.t('Cameras')}
data-name="cameras"
/>
Expand All @@ -151,19 +164,20 @@ class App extends GenericApp {
<div style={this.isIFrame ? styles.tabContentIFrame : styles.tabContent}>
{(this.state.selectedTab === 'options' || !this.state.selectedTab) && (
<TabOptions
key="options"
themeType={this.state.themeType}
common={this.common}
socket={this.socket}
native={this.state.native}
encrypt={(value, cb) => cb(this.encrypt(value))}
decrypt={(value, cb) => cb(this.decrypt(value))}
native={this.state.native as CamerasInstanceNative}
onError={text => this.setState({ errorText: text })}
onLoad={native => this.onLoadConfig(native)}
instance={this.instance}
theme={this.state.theme}
getIpAddresses={() => this.socket.getIpAddresses(this.common.host)}
getIpAddresses={() =>
this.common?.host
? this.socket.getIpAddresses(this.common.host)
: Promise.resolve([])
}
getExtendableInstances={() => this.getExtendableInstances()}
onConfigError={configError => this.setConfigurationError(configError)}
adapterName={this.adapterName}
onChange={(attr, value, cb) => this.updateNativeValue(attr, value, cb)}
instanceAlive={this.state.alive}
Expand All @@ -177,10 +191,14 @@ class App extends GenericApp {
themeType={this.state.themeType}
adapterName={this.adapterName}
instance={this.instance}
encrypt={(value, cb) => cb(this.encrypt(value))}
decrypt={(value, cb) => cb(this.decrypt(value))}
encrypt={(textToEncrypt: string, cb: (encryptedText: string) => void): void =>
cb(this.encrypt(textToEncrypt))
}
decrypt={(textToDecrypt: string, cb: (decryptedText: string) => void): void =>
cb(this.decrypt(textToDecrypt))
}
instanceAlive={this.state.alive}
native={this.state.native}
native={this.state.native as CamerasInstanceNative}
onChange={(attr, value, cb) => this.updateNativeValue(attr, value, cb)}
/>
)}
Expand Down
Loading

0 comments on commit 65a2a84

Please sign in to comment.