socket in client, new set of icons

This commit is contained in:
michalcourson
2026-02-28 11:17:37 -05:00
parent 69c9d80a82
commit ab57d8ef22
43 changed files with 114 additions and 81 deletions

View File

@ -18,6 +18,8 @@ import { resolveHtmlPath } from './util';
import registerFileIpcHandlers from '../ipc/audio/main';
import PythonSubprocessManager from './service';
const pythonManager = new PythonSubprocessManager('src/main.py');
class AppUpdater {
constructor() {
log.transports.file.level = 'info';
@ -124,6 +126,7 @@ const createWindow = async () => {
app.on('window-all-closed', () => {
// Respect the OSX convention of having the application in memory even
// after all windows have been closed
pythonManager.stop();
if (process.platform !== 'darwin') {
app.quit();
}
@ -132,8 +135,7 @@ app.on('window-all-closed', () => {
app
.whenReady()
.then(() => {
const pythonManager = new PythonSubprocessManager('src/main.py');
pythonManager.start();
// pythonManager.start();
createWindow();
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the

View File

@ -67,32 +67,11 @@ const metadataSlice = createSlice({
targetState.clips.push(clip);
}
},
addNewClips(state, action) {
const { collections } = action.payload;
Object.keys(collections).forEach((collection) => {
const collectionState = state.collections.find(
(col) => col.name === collection,
);
if (!collectionState) {
state.collections.push({
name: collection,
id: Date.now(),
clips: [],
});
}
const existingFilenames = new Set(
state.collections
.find((col) => col.name === collection)
?.clips.map((clip) => clip.filename) || [],
);
const newClips = collections[collection].filter(
(clip: ClipMetadata) => !existingFilenames.has(clip.filename),
);
// const collectionState = state.collections.find(
// (col) => col.name === collection,
// );
if (collectionState) {
collectionState.clips.push(...newClips);
addNewClip(state, action) {
const { clip } = action.payload;
state.collections.forEach((collection) => {
if (collection.name === 'Uncategorized') {
collection.clips.push(clip);
}
});
},
@ -113,6 +92,6 @@ export type RootState = ReturnType<AppStore['getState']>;
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = AppStore['dispatch'];
export const { setCollections, addNewClips, addCollection } =
export const { setCollections, addNewClip, addCollection } =
metadataSlice.actions;
export default metadataSlice.reducer;

View File

@ -7,6 +7,7 @@ import { ThemeProvider, createTheme } from '@mui/material/styles';
import DialogTitle from '@mui/material/DialogTitle';
import DialogContent from '@mui/material/DialogContent';
import DialogActions from '@mui/material/DialogActions';
import io from 'socket.io-client';
// import 'tailwindcss/tailwind.css';
import './App.css';
import ClipList from './components/ClipList';
@ -14,7 +15,7 @@ import { useAppDispatch, useAppSelector } from './hooks';
import { store } from '../redux/main';
import { useNavigate } from 'react-router-dom';
import SettingsPage from './Settings';
import apiFetch from './api';
import { apiFetch, getBaseUrl } from './api';
function MainPage() {
const dispatch = useAppDispatch();
@ -27,20 +28,46 @@ function MainPage() {
const [newCollectionOpen, setNewCollectionOpen] = useState(false);
const [newCollectionName, setNewCollectionName] = useState<string>('');
const navigate = useNavigate();
const [socket, setSocket] = useState<any>(null);
useEffect(() => {}, []);
useEffect(() => {
const fetchMetadata = async () => {
try {
const response = await apiFetch('meta');
const data = await response.json();
dispatch({ type: 'metadata/setAllData', payload: data });
} catch (error) {
console.error('Error fetching metadata:', error);
}
const initializeSocket = async () => {
const baseUrl = await getBaseUrl();
const newSocket = io(baseUrl);
setSocket(newSocket);
newSocket.on('connect', () => {
console.log('Connected to WebSocket server');
});
newSocket.on('full_data', (data: any) => {
console.log('Received full_data from server:', data);
dispatch({
type: 'metadata/setAllData',
payload: { collections: data },
});
});
newSocket.on('new_clip', (data: any) => {
console.log('Received new_clips from server:', data);
dispatch({
type: 'metadata/addNewClip',
payload: { clip: data },
});
});
};
fetchMetadata();
const intervalId = setInterval(fetchMetadata, 5000);
return () => clearInterval(intervalId);
initializeSocket();
// const fetchMetadata = async () => {
// try {
// const response = await apiFetch('meta');
// const data = await response.json();
// dispatch({ type: 'metadata/setAllData', payload: data });
// } catch (error) {
// console.error('Error fetching metadata:', error);
// }
// };
// fetchMetadata();
// const intervalId = setInterval(fetchMetadata, 5000);
// return () => clearInterval(intervalId);
}, [dispatch]);
useEffect(() => {

View File

@ -5,7 +5,7 @@ import './App.css';
import TextField from '@mui/material/TextField';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import apiFetch from './api';
import { apiFetch } from './api';
type AudioDevice = {
index: number;

View File

@ -1,4 +1,4 @@
const getBaseUrl = async () => {
export const getBaseUrl = async () => {
const port = await window.audio.getPort();
if (port.error || !port.port) {
return `http://localhost:5010`;
@ -7,7 +7,7 @@ const getBaseUrl = async () => {
return `http://localhost:${port.port}`;
};
export default async function apiFetch(endpoint: string, options = {}) {
export async function apiFetch(endpoint: string, options = {}) {
const url = `${await getBaseUrl()}/${endpoint}`;
return fetch(url, options);
}

View File

@ -15,7 +15,7 @@ import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
import AudioTrimmer from './AudioTrimer';
import { ClipMetadata } from '../../redux/types';
import { useAppDispatch, useAppSelector } from '../hooks';
import apiFetch from '../api';
import { apiFetch } from '../api';
export interface ClipListProps {
collection: string;