Merge pull request #553 from ImUrX/eslint-actions

ESLint action for GUI
This commit is contained in:
Eiren Rain
2023-02-09 17:41:50 +02:00
committed by GitHub
29 changed files with 108 additions and 159 deletions

View File

@@ -17,6 +17,26 @@ on:
create:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version-file: '.node-version'
cache: 'npm'
- name: Build
run: |
npm ci
cd gui
npm run lint
build:
strategy:
fail-fast: false

View File

@@ -27,7 +27,15 @@
"no-inline-styles": "off",
"@typescript-eslint/no-explicit-any": "off",
"react/no-unescaped-entities": "off",
"prettier/prettier": "warn"
"prettier/prettier": "warn",
"camelcase": "error",
"@typescript-eslint/no-unused-vars": [
"warn",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
]
},
"settings": {
"import/resolver": {

View File

@@ -37,9 +37,9 @@
"dev": "tauri dev",
"skipbundler": "tauri build -b none",
"tauri": "tauri",
"lint": "eslint src/**/*.{js,jsx,ts,tsx,json}",
"lint:fix": "eslint --fix src/**/*.{js,jsx,ts,tsx,json}",
"format": "prettier --write src/**/*.{js,jsx,ts,tsx,css,md,json} --config ./.prettierrc",
"lint": "eslint \"src/**/*.{js,jsx,ts,tsx,json}\"",
"lint:fix": "eslint --fix \"src/**/*.{js,jsx,ts,tsx,json}\"",
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,md,json}\"",
"preview-vite": "vite preview",
"javaversion-build": "cd src-tauri/src/ && javac JavaVersion.java && jar cvfe JavaVersion.jar JavaVersion JavaVersion.class"
},

View File

@@ -116,8 +116,8 @@ export default function App() {
const unlisten = listen(
'server-status',
(event: Event<[string, string]>) => {
const [event_type, s] = event.payload;
if ('stderr' === event_type) {
const [eventType, s] = event.payload;
if ('stderr' === eventType) {
// This strange invocation is what lets us lose the line information in the console
// See more here: https://stackoverflow.com/a/48994308
setTimeout(
@@ -128,7 +128,7 @@ export default function App() {
'color:red'
)
);
} else if (event_type === 'stdout') {
} else if (eventType === 'stdout') {
setTimeout(
console.log.bind(
console,
@@ -137,11 +137,11 @@ export default function App() {
'color:green'
)
);
} else if (event_type === 'error') {
} else if (eventType === 'error') {
console.error('Error: %s', s);
} else if (event_type === 'terminated') {
} else if (eventType === 'terminated') {
console.error('Server Process Terminated: %s', s);
} else if (event_type === 'other') {
} else if (eventType === 'other') {
console.log('Other process event: %s', s);
}
}

View File

@@ -1,8 +1,6 @@
import classNames from 'classnames';
import { ReactNode, useEffect, useState } from 'react';
import {
DriftCompensationSettings,
DriftCompensationSettingsT,
ResetType,
RpcMessage,
SettingsRequestT,

View File

@@ -5,7 +5,7 @@ import {
useLayoutEffect,
useMemo,
useRef,
useState
useState,
} from 'react';
import { BodyPart, TrackerDataT } from 'solarxr-protocol';
import { FlatDeviceTracker } from '../../hooks/app';

View File

@@ -5,7 +5,7 @@ import { EyeIcon } from './icon/EyeIcon';
interface InputProps {
variant?: 'primary' | 'secondary';
label: string;
label?: string;
name: string;
}
@@ -13,7 +13,7 @@ export const InputInside = forwardRef<
HTMLInputElement,
{
variant?: 'primary' | 'secondary';
label: string;
label?: string;
onChange: () => void;
} & Partial<HTMLInputElement>
>(function AppInput(

View File

@@ -1,4 +1,4 @@
export function CheckIcon(props: any) {
export function CheckIcon(_props: any) {
return (
<svg
width="9"

View File

@@ -1,4 +1,3 @@
import { useLocalization } from '@fluent/react';
import { useMemo } from 'react';
import { BodyPart } from 'solarxr-protocol';
import { FlatDeviceTracker } from '../../hooks/app';
@@ -15,7 +14,6 @@ export function BodyAssignment({
onlyAssigned: boolean;
onRoleSelected: (role: BodyPart) => void;
}) {
const { l10n } = useLocalization();
const { useAssignedTrackers } = useTrackers();
const assignedTrackers = useAssignedTrackers();

View File

@@ -5,7 +5,7 @@ import {
ReactNode,
useEffect,
useRef,
useState
useState,
} from 'react';
import { useElemSize } from '../../hooks/layout';
import { CheckIcon } from '../commons/icon/CheckIcon';

View File

@@ -14,7 +14,7 @@ import {
SettingsRequestT,
SettingsResponseT,
SteamVRTrackersSettingT,
TapDetectionSettingsT
TapDetectionSettingsT,
} from 'solarxr-protocol';
import { useConfig } from '../../../hooks/config';
import { useWebsocketAPI } from '../../../hooks/websocket-api';

View File

@@ -8,7 +8,7 @@ import {
OSCSettingsT,
RpcMessage,
SettingsRequestT,
SettingsResponseT
SettingsResponseT,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { CheckBox } from '../../commons/Checkbox';
@@ -45,7 +45,7 @@ export function OSCRouterSettings() {
const { state } = useLocation();
const pageRef = useRef<HTMLFormElement | null>(null);
const { reset, control, watch, handleSubmit, register } =
const { reset, control, watch, handleSubmit } =
useForm<OSCRouterSettingsForm>({
defaultValues: defaultValues,
});

View File

@@ -9,7 +9,7 @@ import {
RpcMessage,
SettingsRequestT,
SettingsResponseT,
VRCOSCSettingsT
VRCOSCSettingsT,
} from 'solarxr-protocol';
import { useWebsocketAPI } from '../../../hooks/websocket-api';
import { CheckBox } from '../../commons/Checkbox';
@@ -64,10 +64,9 @@ export function VRCOSCSettings() {
const { state } = useLocation();
const pageRef = useRef<HTMLFormElement | null>(null);
const { reset, control, watch, handleSubmit, register } =
useForm<VRCOSCSettingsForm>({
defaultValues: defaultValues,
});
const { reset, control, watch, handleSubmit } = useForm<VRCOSCSettingsForm>({
defaultValues: defaultValues,
});
const onSubmit = (values: VRCOSCSettingsForm) => {
const settings = new ChangeSettingsRequestT();

View File

@@ -51,7 +51,7 @@ export function TrackerSettingsPage() {
trackernum: string;
deviceid: string;
}>();
const { control, register, watch, reset, handleSubmit } = useForm<{
const { control, watch, reset, handleSubmit } = useForm<{
trackerName: string | null;
allowDriftCompensation: boolean | null;
}>({
@@ -335,7 +335,8 @@ export function TrackerSettingsPage() {
type="text"
name="trackerName"
control={control}
autocomplete={false}
autocomplete="false"
rules={undefined}
></Input>
</div>
</div>

View File

@@ -47,17 +47,13 @@ export function reducer(state: AppState, action: AppStateAction) {
}
export function useProvideAppContext(): AppContext {
const { sendDataFeedPacket, useDataFeedPacket, isConnected } =
useWebsocketAPI();
const { sendDataFeedPacket, useDataFeedPacket, isConnected } = useWebsocketAPI();
const { config } = useConfig();
const { dataFeedConfig } = useDataFeedConfig();
const navigate = useNavigate();
const [state, dispatch] = useReducer<Reducer<AppState, AppStateAction>>(
reducer,
{
datafeed: new DataFeedUpdateT(),
}
);
const [state, dispatch] = useReducer<Reducer<AppState, AppStateAction>>(reducer, {
datafeed: new DataFeedUpdateT(),
});
useEffect(() => {
if (isConnected) {
@@ -85,12 +81,9 @@ export function useProvideAppContext(): AppContext {
[state]
);
useDataFeedPacket(
DataFeedMessage.DataFeedUpdate,
(packet: DataFeedUpdateT) => {
dispatch({ type: 'datafeed', value: packet });
}
);
useDataFeedPacket(DataFeedMessage.DataFeedUpdate, (packet: DataFeedUpdateT) => {
dispatch({ type: 'datafeed', value: packet });
});
return {
state,

View File

@@ -28,9 +28,7 @@ export function useProvideAutobone(): AutoboneContext {
const [hasRecording, setHasRecording] = useState(false);
const [hasCalibration, setHasCalibration] = useState(false);
const [progress, setProgress] = useState(0);
const [skeletonParts, setSkeletonParts] = useState<SkeletonPartT[] | null>(
null
);
const [skeletonParts, setSkeletonParts] = useState<SkeletonPartT[] | null>(null);
const bodyParts = useMemo(() => {
return (
@@ -81,11 +79,7 @@ export function useProvideAutobone(): AutoboneContext {
if (data.processType) {
if (data.message) {
console.log(
AutoBoneProcessType[data.processType],
': ',
data.message
);
console.log(AutoBoneProcessType[data.processType], ': ', data.message);
}
if (data.total > 0 && data.current >= 0) {
@@ -123,25 +117,22 @@ export function useProvideAutobone(): AutoboneContext {
}
);
useRPCPacket(
RpcMessage.AutoBoneEpochResponse,
(data: AutoBoneEpochResponseT) => {
setProgress(data.currentEpoch / data.totalEpochs);
useRPCPacket(RpcMessage.AutoBoneEpochResponse, (data: AutoBoneEpochResponseT) => {
setProgress(data.currentEpoch / data.totalEpochs);
// Probably not necessary to show to the user
console.log(
'Epoch ',
data.currentEpoch,
'/',
data.totalEpochs,
' (Error ',
data.epochError,
')'
);
// Probably not necessary to show to the user
console.log(
'Epoch ',
data.currentEpoch,
'/',
data.totalEpochs,
' (Error ',
data.epochError,
')'
);
setSkeletonParts(data.adjustedSkeletonParts);
}
);
setSkeletonParts(data.adjustedSkeletonParts);
});
return {
hasCalibration,
@@ -154,9 +145,7 @@ export function useProvideAutobone(): AutoboneContext {
};
}
export const AutoboneContextC = createContext<AutoboneContext>(
undefined as any
);
export const AutoboneContextC = createContext<AutoboneContext>(undefined as any);
export function useAutobone() {
const context = useContext<AutoboneContext>(AutoboneContextC);

View File

@@ -3,7 +3,7 @@ import {
createDir,
readTextFile,
renameFile,
writeFile
writeFile,
} from '@tauri-apps/api/fs';
import { createContext, useContext, useRef, useState } from 'react';

View File

@@ -1,8 +1,4 @@
import {
DataFeedConfigT,
DeviceDataMaskT,
TrackerDataMaskT,
} from 'solarxr-protocol';
import { DataFeedConfigT, DeviceDataMaskT, TrackerDataMaskT } from 'solarxr-protocol';
import { useConfig } from './config';
export function useDataFeedConfig() {

View File

@@ -1,12 +1,4 @@
import {
MutableRefObject,
Ref,
useEffect,
useLayoutEffect,
useMemo,
useRef,
useState,
} from 'react';
import { MutableRefObject, useEffect, useLayoutEffect, useRef, useState } from 'react';
export function useLayout<T extends HTMLElement>() {
const [layoutHeight, setLayoutHeigt] = useState(window.innerHeight);

View File

@@ -1,12 +1,5 @@
import {
createContext,
Reducer,
useContext,
useEffect,
useLayoutEffect,
useReducer,
} from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { createContext, Reducer, useContext, useLayoutEffect, useReducer } from 'react';
import { useLocation } from 'react-router-dom';
import { useConfig } from './config';
type OnboardingAction =
@@ -51,18 +44,18 @@ export function reducer(state: OnboardingState, action: OnboardingAction) {
export function useProvideOnboarding(): OnboardingContext {
const { setConfig } = useConfig();
const [state, dispatch] = useReducer<
Reducer<OnboardingState, OnboardingAction>
>(reducer, {
progress: 0,
alonePage: false,
});
const [state, dispatch] = useReducer<Reducer<OnboardingState, OnboardingAction>>(
reducer,
{
progress: 0,
alonePage: false,
}
);
const { state: locatioState } = useLocation();
useLayoutEffect(() => {
const { alonePage = false }: { alonePage?: boolean } =
(locatioState as any) || {};
const { alonePage = false }: { alonePage?: boolean } = (locatioState as any) || {};
if (alonePage !== state.alonePage)
dispatch({ type: 'alone-page', value: alonePage });
@@ -84,16 +77,12 @@ export function useProvideOnboarding(): OnboardingContext {
};
}
export const OnboardingContextC = createContext<OnboardingContext>(
undefined as any
);
export const OnboardingContextC = createContext<OnboardingContext>(undefined as any);
export function useOnboarding() {
const context = useContext<OnboardingContext>(OnboardingContextC);
if (!context) {
throw new Error(
'useOnboarding must be within a OnboardingContext Provider'
);
throw new Error('useOnboarding must be within a OnboardingContext Provider');
}
return context;
}

View File

@@ -16,9 +16,7 @@ export type PayloadType = MessageT['payloadType'];
export function usePubSub() {
const { sendPubSubPacket, usePubSubPacket } = useWebsocketAPI();
const [handleTopics, setHandleTopics] = useState<{ [key: number]: TopicIdT }>(
{}
);
const [handleTopics, setHandleTopics] = useState<{ [key: number]: TopicIdT }>({});
const subscribe = (
topicId: TopicIdT,
@@ -78,11 +76,7 @@ export function usePubSub() {
};
}
export const topic = ({
appName,
organization,
topic,
}: Omit<TopicIdT, 'pack'>) =>
export const topic = ({ appName, organization, topic }: Omit<TopicIdT, 'pack'>) =>
Object.assign(new TopicIdT(), { appName, organization, topic });
export const OVERLAY_DISPLAY_SETTINGS_TOPIC = topic({

View File

@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect } from 'react';
export function useTimeout(fn: () => void, delay: number) {
useEffect(() => {
@@ -14,11 +14,7 @@ export function useInterval(fn: () => void, delay: number) {
});
}
export const useDebouncedEffect = (
effect: () => void,
deps: any[],
delay: number
) => {
export const useDebouncedEffect = (effect: () => void, deps: any[], delay: number) => {
useEffect(() => {
const handler = setTimeout(() => effect(), delay);

View File

@@ -19,22 +19,14 @@ export interface WebSocketApi {
isFirstConnection: boolean;
reconnect: () => void;
useRPCPacket: <T>(type: RpcMessage, callback: (packet: T) => void) => void;
useDataFeedPacket: <T>(
type: DataFeedMessage,
callback: (packet: T) => void
) => void;
useDataFeedPacket: <T>(type: DataFeedMessage, callback: (packet: T) => void) => void;
sendRPCPacket: (type: RpcMessage, data: RPCPacketType) => void;
sendDataFeedPacket: (type: DataFeedMessage, data: DataFeedPacketType) => void;
usePubSubPacket: <T>(
type: PubSubUnion,
callback: (packet: T) => void
) => void;
usePubSubPacket: <T>(type: PubSubUnion, callback: (packet: T) => void) => void;
sendPubSubPacket: (type: PubSubUnion, data: PubSubPacketType) => void;
}
export const WebSocketApiContext = createContext<WebSocketApi>(
undefined as never
);
export const WebSocketApiContext = createContext<WebSocketApi>(undefined as never);
export type RPCPacketType = RpcMessageHeaderT['message'];
export type PubSubPacketType = PubSubHeaderT['u'];
@@ -142,10 +134,7 @@ export function useProvideWebsocketApi(): WebSocketApi {
webSocketRef.current.send(fbb.asUint8Array());
};
const sendPubSubPacket = (
type: PubSubUnion,
data: PubSubPacketType
): void => {
const sendPubSubPacket = (type: PubSubUnion, data: PubSubPacketType): void => {
if (webSocketRef?.current?.readyState !== WebSocket.OPEN) return;
const fbb = new Builder(1);
@@ -198,18 +187,12 @@ export function useProvideWebsocketApi(): WebSocketApi {
isConnected,
isFirstConnection,
reconnect,
useDataFeedPacket: <T>(
type: DataFeedMessage,
callback: (packet: T) => void
) => {
useDataFeedPacket: <T>(type: DataFeedMessage, callback: (packet: T) => void) => {
useEffect(() => {
const onEvent = (event: CustomEventInit) => {
callback(event.detail);
};
datafeedlistenerRef.current.addEventListener(
DataFeedMessage[type],
onEvent
);
datafeedlistenerRef.current.addEventListener(DataFeedMessage[type], onEvent);
return () => {
datafeedlistenerRef.current.removeEventListener(
DataFeedMessage[type],
@@ -236,10 +219,7 @@ export function useProvideWebsocketApi(): WebSocketApi {
};
pubsublistenerRef.current.addEventListener(PubSubUnion[type], onEvent);
return () => {
pubsublistenerRef.current.removeEventListener(
PubSubUnion[type],
onEvent
);
pubsublistenerRef.current.removeEventListener(PubSubUnion[type], onEvent);
};
}, [callback, type]);
},

View File

@@ -1,8 +1,6 @@
import { Localized } from '@fluent/react';
import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { Input } from '../components/commons/Input';
import { useOnboarding } from './onboarding';
export interface WifiFormData {

View File

@@ -11,7 +11,6 @@ import {
} from 'react';
import { exists, readTextFile, BaseDirectory } from '@tauri-apps/api/fs';
export const defaultNS = 'translation';
export const DEFAULT_LOCALE = 'en';
const OVERRIDE_FILENAME = 'override.ftl';

View File

@@ -4,7 +4,7 @@
body {
font-variant-numeric: tabular-nums;
font-family: 'poppins', sans-serif, "Twemoji";
font-family: 'poppins', sans-serif, 'Twemoji';
height: 100vh;
width: 100vw;
user-select: none;

View File

@@ -17,14 +17,12 @@ export function QuaternionToQuatT(q: QuatObject) {
return quat;
}
export function MountingOrientationDegreesToQuatT(
mountingOrientationDegrees: number
) {
export function MountingOrientationDegreesToQuatT(mountingOrientationDegrees: number) {
return QuaternionToQuatT(
new Quaternion().setFromEuler(
new Euler(0, +mountingOrientationDegrees * DEG_TO_RAD, 0)
)
)
);
}
const RAD_TO_DEG = 180 / Math.PI;

View File

@@ -1,7 +1,7 @@
import { Vec3fT } from 'solarxr-protocol';
import { Vector3 } from 'three';
export type Vector3Object = { x: number; y: number; z: number; };
export type Vector3Object = { x: number; y: number; z: number };
export function Vector3FromVec3fT(vec?: Vector3Object | null) {
return vec ? new Vector3(vec.x, vec.y, vec.z) : new Vector3();

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line spaced-comment
/// <reference types="vite/client" />
declare const __COMMIT_HASH__: string;