Skip to content

Commit

Permalink
refactor: Change project folder structure
Browse files Browse the repository at this point in the history
  • Loading branch information
gmallios committed Mar 9, 2024
1 parent f5a2a03 commit 959feea
Show file tree
Hide file tree
Showing 84 changed files with 4,038 additions and 628 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,4 @@ test_video.mp4
/tooling/cli.rs

# UI Build directory
/dist/*
*/dist/*
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[workspace]
resolver = "2"
members = [
"src-tauri",
"manager-app",
"soundcore-lib",
"test_data"
]
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml → manager-app/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "soundcoremanager"
name = "manager-app"
version = "0.1.1"
description = "A Tauri desktop app for managing Soundcore devices"
authors = ["Grigorios Mallios"]
Expand Down
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json → manager-app/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"beforeDevCommand": "yarn dev",
"beforeBuildCommand": "yarn build",
"devPath": "http://localhost:1420",
"distDir": "../dist"
"distDir": "../manager-ui/dist"
},
"package": {
"productName": "Soundcore Manager",
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
5 changes: 2 additions & 3 deletions index.html → manager-ui/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri + React + TS</title>
<title>Soundcore Manager</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script type="module" src="src/main.tsx"></script>
</body>
</html>
50 changes: 50 additions & 0 deletions manager-ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "manager-ui",
"version": "0.1.0",
"type": "module",
"scripts": {
"lint": "eslint ./manager-ui",
"lint:fix": "eslint --fix ./manager-ui",
"format": "prettier --write './**/*.{js,jsx,ts,tsx,css,md,json}' --config ./.prettierrc",
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"tauri": "tauri",
"generate-types": "yarn typeshare:tauri && yarn typeshare:soundcore-lib",
"typeshare:soundcore-lib": "typeshare ./soundcore-lib --lang=typescript --output-file=./src/types/soundcore-lib.d.ts",
"typeshare:tauri": "typeshare ./src-tauri --lang=typescript --output-file=./src/types/tauri-backend.d.ts"
},
"dependencies": {
"@emotion/react": "^11.10.4",
"@emotion/styled": "^11.10.4",
"@fontsource/roboto": "^4.5.8",
"@mui/icons-material": "^5.11.16",
"@mui/material": "^5.12.0",
"@tanstack/react-query": "^4.20.4",
"@tanstack/react-query-devtools": "^4.20.4",
"@tauri-apps/api": "^1.5.0",
"chart.js": "~3.9.1",
"chartjs-plugin-dragdata": "^2.2.4",
"react": "^18.2.0",
"react-chartjs-2": "^4.3.1",
"react-dom": "^18.2.0",
"tauri-plugin-log-api": "https://github.com/tauri-apps/tauri-plugin-log#v1",
"zustand": "^4.5.2"
},
"devDependencies": {
"@tauri-apps/cli": "^1.5.1",
"@types/node": "^18.7.10",
"@types/react": "^18.2.6",
"@types/react-dom": "^18.0.6",
"@typescript-eslint/eslint-plugin": "^7.1.0",
"@typescript-eslint/parser": "^7.1.0",
"@vitejs/plugin-react": "^4.0.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.33.2",
"prettier": "^3.2.5",
"typescript": "^5.0.4",
"vite": "^5.1.5"
}
}
File renamed without changes.
26 changes: 26 additions & 0 deletions manager-ui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import './App.css';
import { useSoundcoreStore } from './stores/useSoundcoreStore';
import { BluetoothSearchScreen } from './screens/bluetoothSearch';
import { useAsyncBridgeEvent } from './hooks/useAsyncBridge';
import { useShallow } from 'zustand/react/shallow';

export const App: React.FC = () => {
const [handleAsyncBridgeEvent, connectedDevices] = useSoundcoreStore(
useShallow((state) => [state.handleAsyncBridgeEvent, state.connectedDevices])
);

// Add the event listener to the bridge, which listener is
// provided by the store.
useAsyncBridgeEvent((event) => {
handleAsyncBridgeEvent(event);
});

return (
<React.Fragment>
{connectedDevices.length !== 0 ? <h1>Some connected devices!</h1> : <BluetoothSearchScreen />}
</React.Fragment>
);
};

export default App;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Event, listen } from '@tauri-apps/api/event';
import { useEffect } from 'react';
import { BridgeResponse } from '../types/tauri-backend';
import { BridgeCommand, BridgeResponse } from '../types/tauri-backend';
import { invoke } from '@tauri-apps/api/tauri';

export const AsyncBridgeEvent = 'async-bridge-event';
export const AsyncBridgeRequest = 'send_bridge_command';

export const useAsyncBridgeEvent = (cb: (event: Event<BridgeResponse>) => void) => {
return useEffect(() => {
const unlisten = async () => {
await listen('async-bridge-event', (event: Event<BridgeResponse>) => {
await listen(AsyncBridgeEvent, (event: Event<BridgeResponse>) => {
cb(event as Event<BridgeResponse>);
});
};
Expand All @@ -19,3 +23,7 @@ export const useAsyncBridgeEvent = (cb: (event: Event<BridgeResponse>) => void)
};
}, [cb]);
};

export const useAsyncBridgeRequest = (command: BridgeCommand): Promise<void> => {
return invoke(AsyncBridgeRequest, { payload: command });
};
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 0 additions & 2 deletions src/main.tsx → manager-ui/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import './style.css';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { appLogDir } from '@tauri-apps/api/path';
import { attachConsole } from 'tauri-plugin-log-api';

Expand Down Expand Up @@ -37,7 +36,6 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<CssBaseline />
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools />
</QueryClientProvider>
</ThemeProvider>
);
131 changes: 131 additions & 0 deletions manager-ui/src/screens/bluetoothSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import React from 'react';
import { useSoundcoreStore } from '../stores/useSoundcoreStore';
import Stack from '@mui/material/Stack/Stack';
import {
Container,
Fab,
LinearProgress,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
Typography
} from '@mui/material';
import { useShallow } from 'zustand/react/shallow';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
import { DiscoveredDevice } from '../types/soundcore-lib';
import BluetoothIcon from '@mui/icons-material/Bluetooth';

export const BluetoothSearchScreen: React.FC = () => {
const { isLoading, startScan, latestScanResults } = useSoundcoreStore(
useShallow((state) => ({
isLoading: state.isLoading,
startScan: state.startScan,
latestScanResults: state.latestScan
}))
);

const [selectedDevice, setSelectedDevice] = React.useState<DiscoveredDevice>();

const connectFabClick = () => {
console.log(selectedDevice);
};

// useEffect(() => {
// startScan();
// }, []);

return (
<div>
<Stack
sx={{
mb: 2,
mt: 2,
width: '100vw',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
<Container
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column',
gap: '0.5rem'
}}>
<Typography color="text.secondary">Select a connected device...</Typography>
{isLoading && <LinearProgress sx={{ width: '100vw', height: '0.15rem' }} />}
{!isLoading && <div style={{ width: '100vw', height: '0.15rem' }}></div>}
</Container>
{latestScanResults && (
<BluetoothDeviceList devices={latestScanResults} setSelectedDevice={setSelectedDevice} />
)}
<Fab
onClick={() => connectFabClick()}
variant="extended"
size="medium"
color="primary"
aria-label="add"
sx={{ position: 'absolute', bottom: 16, right: 16 }}>
Connect
<ArrowForwardIcon sx={{ ml: 1 }} />
</Fab>
<Fab
onClick={() => startScan()}
variant="extended"
size="medium"
color="primary"
aria-label="add"
sx={{ position: 'absolute', bottom: 16, left: 16 }}>
Refresh List
</Fab>
</Stack>
</div>
);
};

const BluetoothDeviceList: React.FC<{
devices: DiscoveredDevice[];
setSelectedDevice: (device: DiscoveredDevice) => void;
}> = ({ devices, setSelectedDevice }) => {
const [selectedIndex, setSelectedIndex] = React.useState<number>();

const onItemClicked = (idx: number) => {
setSelectedDevice(devices[idx]);
setSelectedIndex(idx);
};

return (
<List sx={{ width: '100vw' }}>
{devices.map((device, idx) => (
<BluetoothDeviceListItem
key={idx}
idx={idx}
device={device}
onClick={onItemClicked}
selected={selectedIndex === idx}
/>
))}
</List>
);
};

const BluetoothDeviceListItem: React.FC<{
idx: number;
device: DiscoveredDevice;
onClick: (idx: number) => void;
selected?: boolean;
}> = ({ idx, device, onClick, selected }) => {
return (
<ListItem disablePadding>
<ListItemButton selected={selected} onClick={() => onClick(idx)}>
<ListItemIcon>
<BluetoothIcon />
</ListItemIcon>
<ListItemText primary={device.descriptor.name} />
</ListItemButton>
</ListItem>
);
};
13 changes: 4 additions & 9 deletions src/stores/baseSlice.tsx → manager-ui/src/stores/baseSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { StateCreator, StoreApi } from 'zustand';
import { SoundcoreStoreSlices } from './useSoundcoreStore';
import { BridgeResponse } from '../types/tauri-backend';

export interface BaseSlice {
handleAsyncBridgeEvent: (e: Event<BridgeResponse>) => void;
}

export const createBaseSlice: StateCreator<SoundcoreStoreSlices, [], [], BaseSlice> = (
set,
get
) => ({
handleAsyncBridgeEvent: (e: Event<BridgeResponse>) => {
console.log('Handling async bridge event', e);

const payload = e.payload as BridgeResponse;
const kind = e.payload.kind as BridgeResponse['kind'];
const handler = bridgeResponseHandlers[kind];
Expand All @@ -28,11 +30,9 @@ type BridgeResponseHandlers = {
};
const bridgeResponseHandlers: BridgeResponseHandlers = {
newState: (payload, _set, get) => {
console.log('Handling new state', payload);
get().setStateFromBridgeResponse(payload);
},
scanResult: function (payload, _set, get): void {
console.log('Handling scan result', payload);
get().setLatestScan(payload);
},
connectionEstablished: function (_e, _set, _get): void {
Expand All @@ -45,8 +45,3 @@ const bridgeResponseHandlers: BridgeResponseHandlers = {
throw new Error('Function not implemented.');
}
};

// TODO: Add types
export interface BaseSlice {
handleAsyncBridgeEvent: (e: Event<BridgeResponse>) => void;
}
30 changes: 30 additions & 0 deletions manager-ui/src/stores/bluetoothSlice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { StateCreator } from 'zustand';
import { BluetoothAdrr, DiscoveredDevice } from '../types/soundcore-lib';
import { useAsyncBridgeRequest } from '../hooks/useAsyncBridge';

export const createBluetoothSlice: StateCreator<BluetoothSlice> = (set, _get) => ({
latestScan: null,
isLoading: false,
hasFailed: false,
connectedDevices: [],
setLatestScan: (scanRes: DiscoveredDevice[]) => set({ latestScan: scanRes, isLoading: false }),
startScan: () => {
useAsyncBridgeRequest({ command: 'scan' })
.then(() => {
set({ isLoading: true });
})
.catch((error) => {
console.error(`Could not start scan. ${error}`);
set({ hasFailed: true });
});
}
});

export interface BluetoothSlice {
latestScan: DiscoveredDevice[] | null;
isLoading: boolean;
hasFailed: boolean;
connectedDevices: Array<BluetoothAdrr>;
setLatestScan: (scanRes: DiscoveredDevice[]) => void;
startScan: () => void;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 959feea

Please sign in to comment.