Skip to content

Commit 042ffb8

Browse files
authored
Merge pull request #210 from scribear/jack-qrcode
Jack qrcode
2 parents 1d9d704 + b73c0e4 commit 042ffb8

12 files changed

Lines changed: 622 additions & 345 deletions

File tree

package-lock.json

Lines changed: 280 additions & 188 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
"@emotion/styled": "^11.6.0",
99
"@material-ui/core": "^4.12.4",
1010
"@material-ui/icons": "^4.11.3",
11-
"@mui/icons-material": "^5.11.16",
12-
"@mui/material": "^5.2.7",
11+
"@mui/icons-material": "^5.16.14",
12+
"@mui/material": "^5.16.14",
1313
"@reduxjs/toolkit": "^1.9.3",
1414
"@testing-library/jest-dom": "^5.16.5",
1515
"@testing-library/react": "^12.1.5",
@@ -36,6 +36,7 @@
3636
"react-color": "^2.19.3",
3737
"react-dom": "^17.0.2",
3838
"react-google-charts": "^3.0.15",
39+
"react-qr-code": "^2.0.15",
3940
"react-redux": "^8.0.5",
4041
"react-scripts": "^5.0.1",
4142
"recordrtc": "^5.6.2",

src/components/api/returnAPI.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export const useRecognition = (sRecog : SRecognition, api : ApiStatus, control :
148148
// Stop current recognizer when switching to another one, if possible
149149
newRecognizer?.stop();
150150
}
151-
}, [api.currentApi, azure, control, streamTextConfig, playbackStatus]);
151+
}, [api.currentApi, azure, control, streamTextConfig, playbackStatus, scribearServerStatus]);
152152

153153
// Start / stop recognizer, if listening toggled
154154
useEffect(() => {

src/components/api/scribearServer/scribearRecognizer.tsx

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ export class ScribearRecognizer implements Recognizer {
2222
private scribearServerStatus : ScribearServerStatus
2323
private socket : WebSocket | null = null
2424
private transcribedCallback : any
25+
private errorCallback?: (e: Error) => void;
2526
private language : string
2627
private recorder?: RecordRTC;
2728
private kSampleRate = 16000;
2829

2930

30-
3131
/**
3232
* Creates an Azure recognizer instance that listens to the default microphone
3333
* and expects speech in the given language
@@ -38,7 +38,6 @@ export class ScribearRecognizer implements Recognizer {
3838
console.log("ScribearRecognizer, new recognizer being created!")
3939
this.language = language;
4040
this.scribearServerStatus = scribearServerStatus;
41-
this._startRecording();
4241
}
4342

4443
private async _startRecording() {
@@ -67,6 +66,11 @@ export class ScribearRecognizer implements Recognizer {
6766
console.log("ScribearRecognizer.start()");
6867
if(this.socket) {return;}
6968

69+
const scribearURL = new URL(this.scribearServerStatus.scribearServerAddress)
70+
if (scribearURL.pathname != '/sink') {
71+
this._startRecording();
72+
}
73+
7074
this.socket = new WebSocket(this.scribearServerStatus.scribearServerAddress);
7175

7276
// this.socket.onopen = (e)=> {...}
@@ -89,6 +93,21 @@ export class ScribearRecognizer implements Recognizer {
8993
this.transcribedCallback([finalBlock], inProgressBlock)
9094
}
9195
};
96+
97+
this.socket.onerror = (event) => {
98+
const error = new Error("WebSocket error");
99+
console.error("WebSocket error event:", event);
100+
this.errorCallback?.(error);
101+
};
102+
103+
this.socket.onclose = (event) => {
104+
console.warn(`WebSocket closed: code=${event.code}, reason=${event.reason}`);
105+
this.socket = null;
106+
if (event.code !== 1000) { // 1000 = normal closure
107+
const error = new Error(`WebSocket closed unexpectedly: code=${event.code}`);
108+
this.errorCallback?.(error);
109+
}
110+
};
92111
}
93112

94113
/**
@@ -120,7 +139,8 @@ export class ScribearRecognizer implements Recognizer {
120139
* @param callback A callback function called with the error object when the event is triggered
121140
*/
122141
onError(callback: (e: Error) => void) {
123-
console.log("ServerRecognizer.onError()");
142+
console.log("ScribearRecognizer.onError()");
143+
this.errorCallback = callback;
124144
}
125145

126146

Lines changed: 69 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,97 @@
11
import * as React from 'react';
22
import { useSelector } from 'react-redux';
33
import { ApiStatus, RootState, DisplayStatus, ControlStatus } from '../../react-redux&middleware/redux/typesImports';
4-
import { createTheme, ThemeProvider, IconButton, MenuIcon, Drawer, Grid, AppBar, Toolbar } from '../../muiImports';
5-
6-
import SideBar from './sidebar/sidebar'
4+
import {
5+
createTheme,
6+
ThemeProvider,
7+
IconButton,
8+
Drawer,
9+
Grid,
10+
AppBar,
11+
Toolbar,
12+
Typography,
13+
// useMediaQuery,
14+
// useTheme
15+
} from '@mui/material';
16+
import MenuIcon from '@mui/icons-material/Menu';
17+
import SideBar from './sidebar/sidebar';
718
import TopBar from './topbar/topBar';
819
import { API_Name } from '../../react-redux&middleware/redux/types/apiEnums';
920

21+
import {
22+
useTheme
23+
} from '@mui/material';
24+
1025
const currTheme = createTheme({
1126
palette: {
1227
primary: {
13-
main: '#ffffff'
14-
}
28+
main: '#ffffff',
29+
contrastText: '#000000'
30+
},
1531
},
1632
});
1733

1834
export default function AppNavBar(props) {
19-
const [state, setState] = React.useState({ isOpen: false });
20-
const apiStatus = useSelector((state: RootState) => {
21-
return state.APIStatusReducer as ApiStatus;
22-
})
23-
const displayStatus = useSelector((state: RootState) => {
24-
return state.DisplayReducer as DisplayStatus;
25-
})
26-
const controlStatus = useSelector((state: RootState) => {
27-
return state.ControlReducer as ControlStatus;
28-
})
29-
35+
const [isDrawerOpen, setDrawerOpen] = React.useState(false);
36+
const apiStatus = useSelector((state: RootState) => state.APIStatusReducer as ApiStatus);
37+
const displayStatus = useSelector((state: RootState) => state.DisplayReducer as DisplayStatus);
38+
const controlStatus = useSelector((state: RootState) => state.ControlReducer as ControlStatus);
3039

31-
let apiDisplayName =API_Name(apiStatus.currentApi)
32-
33-
const myTheme = currTheme
40+
const apiDisplayName = API_Name(apiStatus.currentApi);
41+
const accentColor = displayStatus.secondaryColor;
3442

43+
const theme = useTheme();
44+
// const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
3545

36-
const changeVisibility = () => {
37-
let topbarID = document.getElementById("topbar-wrapper")
38-
if (!displayStatus.menuVisible) {
39-
if (topbarID) {
40-
topbarID.style.opacity = "0"
41-
}
42-
} else {
43-
if (topbarID) {
44-
topbarID.style.opacity = "1"
45-
}
46+
const toggleDrawer = (open: boolean) => (event: React.MouseEvent | React.KeyboardEvent) => {
47+
if (event.type === 'keydown' && ((event as React.KeyboardEvent).key === 'Tab' || (event as React.KeyboardEvent).key === 'Shift')) {
48+
return;
4649
}
47-
}
48-
const changeVisibilityOver = () => {
49-
let topbarID = document.getElementById("topbar-wrapper")
50-
if (topbarID) {
51-
topbarID.style.opacity = "1"
52-
}
53-
}
54-
55-
56-
const toggleDrawer = (open: boolean) => (event: React.MouseEvent) => {
57-
setState({ ...state, isOpen: open });
50+
setDrawerOpen(open);
5851
};
59-
60-
// const dispatch = useDispatch();
61-
let accent_color = displayStatus.secondaryColor;
62-
// if (typeof accent_color === 'undefined') {
63-
// accent_color = "#3f51bf";
64-
// dispatch({type: 'CHANGE_SECONDARY_THEME', payload: accent_color});
65-
// }<Toolbar style={{ backgroundColor: accent_color, display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', padding: '0 10px', }}>
66-
// console.log("Accent Color: ", accent_color); <Toolbar style={{ backgroundColor: accent_color, width: '100%', maxHeight: '10vh', paddingLeft: '10px' }}>
52+
console.log(apiStatus.currentApi)
6753

6854
return (
69-
<AppBar position="fixed" id="topbar-wrapper" onMouseOut={changeVisibility} onMouseOver={changeVisibilityOver} style={{ transition: '0.6s' }}>
70-
<Grid container spacing={2} alignItems="center" >
71-
<Toolbar style={{ backgroundColor: accent_color, width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', padding: '10px' }}>
72-
<Grid item xs={6}>
73-
<Grid container spacing={1} alignItems="center" wrap="wrap">
74-
<Grid item>
75-
<IconButton onClick={toggleDrawer(true)}>
76-
<ThemeProvider theme={myTheme}>
77-
<MenuIcon color="primary" fontSize="large"/>
78-
</ThemeProvider>
55+
<ThemeProvider theme={theme}>
56+
<AppBar position="fixed" id="topbar-wrapper" sx={{ transition: '0.6s', backgroundColor: accentColor }}>
57+
<Toolbar sx={{ width: '100%', minHeight: 56, color: 'white' }}>
58+
<Grid container alignItems="center" justifyContent="space-between">
59+
<Grid container alignItems="center" justifyContent="space-between" sx={{ width: '100%' }}>
60+
{/* Left Section: Menu Icon and Title */}
61+
<Grid item sx={{ display: 'flex', alignItems: 'center' }}>
62+
<IconButton edge="start" sx={{ color: 'white' }} aria-label="menu" onClick={toggleDrawer(true)}>
63+
<MenuIcon />
7964
</IconButton>
80-
<Drawer disableEnforceFocus open={state.isOpen} onClose={toggleDrawer(false)}>
81-
<SideBar isRecording={props.isRecording} onClose={toggleDrawer(false)}/>
65+
<Drawer anchor="left" open={isDrawerOpen} onClose={toggleDrawer(false)}>
66+
<SideBar isRecording={props.isRecording} onClose={toggleDrawer(false)} />
8267
</Drawer>
68+
<Typography variant="h6" noWrap sx={{ color: 'white', paddingLeft: 2 }}>
69+
ScribeAR
70+
</Typography>
8371
</Grid>
84-
<Grid item>
85-
<h3 style={{ textAlign: "left", paddingLeft: '10px' }}>ScribeAR</h3>
72+
73+
{/* Right Section: TopBar (Strictly on one line with padding) */}
74+
<Grid
75+
item
76+
sx={{
77+
display: 'flex',
78+
alignItems: 'center',
79+
whiteSpace: 'nowrap',
80+
flexShrink: 0,
81+
pr: 5
82+
}}
83+
>
84+
<TopBar
85+
theme={theme}
86+
apiDisplayName={apiDisplayName}
87+
listening={controlStatus.listening}
88+
menuVisible={displayStatus.menuVisible}
89+
/>
8690
</Grid>
8791
</Grid>
8892
</Grid>
89-
<Grid item xs={6}>
90-
<TopBar theme={myTheme} apiDisplayName={apiDisplayName} listening={controlStatus.listening} menuVisible={displayStatus.menuVisible}/>
91-
</Grid>
9293
</Toolbar>
93-
</Grid>
94-
</AppBar>
95-
)
96-
97-
98-
99-
100-
// return (
101-
// <AppBar position="fixed" id="topbar-wrapper" onMouseOut={changeVisibility} onMouseOver={changeVisibilityOver} style={{ transition: '0.6s' }}>
102-
// <Grid container spacing={2} alignItems="center" >
103-
// <Toolbar style={{ backgroundColor: displayStatus.secondaryColor, width: '100%', maxHeight: '10vh', paddingLeft: '20px' }}>
104-
// <Grid item xs={6}>
105-
// <Grid container spacing={1} alignItems="center" >
106-
// <Grid item>
107-
// <IconButton onClick={toggleDrawer(true)}>
108-
// <ThemeProvider theme={myTheme}>
109-
// <MenuIcon color="primary" fontSize="large"/>
110-
// </ThemeProvider>
111-
// </IconButton>
112-
// <Drawer disableEnforceFocus open={state.isOpen} onClose={toggleDrawer(false)}>
113-
// <SideBar isRecording={props.isRecording} />
114-
// </Drawer>
115-
// </Grid>
116-
// <Grid item>
117-
// <h2 style={{ textAlign: "left", paddingLeft: '20px' }}>ScribeAR</h2>
118-
// </Grid>
119-
// </Grid>
120-
// </Grid>
121-
// <Grid item xs={6}>
122-
// <Grid container direction="row" justifyContent="flex-end" alignItems="center">
123-
// <Grid item >
124-
// <PickApi theme={currTheme} display={display}/>
125-
// </Grid>
126-
127-
// <Grid item >
128-
// <Listening listening={controlStatus.listening} />
129-
// </Grid>
130-
131-
// <Grid item>
132-
// <MenuHider menuVisible={displayStatus.menuVisible} />
133-
// </Grid>
134-
135-
// <Grid item>
136-
// <Fullscreen />
137-
// </Grid>
138-
// </Grid>
139-
// </Grid>
140-
// </Toolbar>
141-
// </Grid>
142-
// </AppBar>
143-
// )
94+
</AppBar>
95+
</ThemeProvider>
96+
);
14497
}

src/components/navbars/topbar/api/pickApi.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from 'react';
2+
import { useDispatch, useSelector } from "react-redux";
23

34
import {
45
API,
@@ -14,7 +15,6 @@ import {
1415
} from '../../../../react-redux&middleware/redux/typesImports';
1516
import { CancelIcon, CheckCircleIcon, Collapse, DoNotDisturbOnIcon, ErrorIcon, ExpandLess, ExpandMore, IconButton, ListItemButton, ListItemIcon, ListItemText, ThemeProvider, createTheme } from '../../../../muiImports'
1617
import { ListItem } from '@mui/material';
17-
import { useDispatch, useSelector } from 'react-redux';
1818

1919
import AzureSettings from './AzureSettings';
2020
import StreamTextSettings from './StreamTextSettings';
@@ -170,7 +170,7 @@ export default function PickApi(props) {
170170
if (!isArrow) {
171171
let copyStatus = Object.assign({}, apiStatus);
172172
copyStatus.currentApi = api;
173-
let apiName = "Webspeech";
173+
let apiName = "";
174174
//Ugh
175175
copyStatus.azureTranslStatus = STATUS.AVAILABLE;
176176
copyStatus.webspeechStatus = STATUS.AVAILABLE;

0 commit comments

Comments
 (0)