good shet eh?
parent
277d92d97a
commit
fd180cca7a
|
|
@ -12,6 +12,8 @@ async function createWindow() {
|
|||
},
|
||||
});
|
||||
|
||||
browserWindow.setMenu(null);
|
||||
|
||||
/**
|
||||
* If you install `show: true` then it can cause issues when trying to close the window.
|
||||
* Use `show: false` and listener events `ready-to-show` to fix these issues.
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ export default function Sidebar(props: {
|
|||
|
||||
useEffect(() => {
|
||||
if(screenRef === null) return;
|
||||
screenRef.addEventListener('touchstart', pointerDown);
|
||||
screenRef.addEventListener('touchend', pointerUp);
|
||||
screenRef.addEventListener('touchmove', pointerMove);
|
||||
screenRef.addEventListener('touchstart', pointerDown, { passive: true });
|
||||
screenRef.addEventListener('touchend', pointerUp, { passive: true });
|
||||
screenRef.addEventListener('touchmove', pointerMove, { passive: true });
|
||||
// screenRef.addEventListener('pointercancel', pointerUp);
|
||||
return () => {
|
||||
screenRef.removeEventListener('touchstart', pointerDown);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
import { useEffect, useState } from "react";
|
||||
|
||||
|
||||
|
||||
export default function useHover<T extends HTMLElement>(): [
|
||||
(t: T) => void,
|
||||
boolean
|
||||
] {
|
||||
const [value, setValue] = useState(false);
|
||||
const [ref, setRef] = useState<T | null>(null);
|
||||
|
||||
const handleMouseOver = () => setValue(true);
|
||||
const handleMouseOut = () => setValue(false);
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
const node = ref;
|
||||
if (node) {
|
||||
node.addEventListener("mouseover", handleMouseOver);
|
||||
node.addEventListener("mouseout", handleMouseOut);
|
||||
return () => {
|
||||
node.removeEventListener("mouseover", handleMouseOver);
|
||||
node.removeEventListener("mouseout", handleMouseOut);
|
||||
};
|
||||
}
|
||||
},
|
||||
[ref] // Recall only if ref changes
|
||||
);
|
||||
return [setRef, value];
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ export function connectApi(url: string) {
|
|||
const connect = async () => {
|
||||
try {
|
||||
connectionAttempts ++;
|
||||
console.log('connecting to', url);
|
||||
// console.log('connecting to', url);
|
||||
socket = new WebSocket(url);
|
||||
} catch (e) {
|
||||
if(destroy) return;
|
||||
|
|
@ -30,14 +30,12 @@ export function connectApi(url: string) {
|
|||
|
||||
socket.addEventListener('message', (event) => {
|
||||
const {action, data} = JSON.parse(event.data);
|
||||
console.log('[IN]', action, data);
|
||||
// console.debug('[IN]', action, data);
|
||||
const routeFound = routers
|
||||
.map(router => router(action, data))
|
||||
.reduce((a, b) => a + b, 0);
|
||||
if(routeFound === 0) {
|
||||
console.warn(`route <${action}> not found`);
|
||||
} else {
|
||||
console.log(`routed to ${routeFound} elements`);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import * as preload from '#preload';
|
||||
|
||||
console.log('#preload', preload);
|
||||
// console.log('#preload', preload);
|
||||
|
||||
const functions: any = (function() {
|
||||
const electron = !!preload.versions;
|
||||
|
|
@ -29,7 +29,7 @@ const functions: any = (function() {
|
|||
})();
|
||||
|
||||
|
||||
console.log('native functions loaded', functions);
|
||||
// console.log('native functions loaded', functions);
|
||||
|
||||
export const getClientId = functions.getClientId;
|
||||
export const setClientId = functions.setClientId;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { useContext, useEffect } from 'react';
|
||||
import { ServerConnectionContext } from '../components/ServerConnection';
|
||||
import useSessionToken from '../hooks/useSessionToken';
|
||||
import { Router, router, RouterObject } from './api';
|
||||
|
||||
export function useApi(actions: Router | RouterObject, deps: any[]) {
|
||||
const connection = useContext(ServerConnectionContext);
|
||||
const _router = typeof actions === 'object' ? router(actions) : actions;
|
||||
const { sessionToken } = useSessionToken();
|
||||
|
||||
useEffect(() => {
|
||||
connection.registerRouter(_router);
|
||||
|
|
@ -14,6 +16,15 @@ export function useApi(actions: Router | RouterObject, deps: any[]) {
|
|||
}, deps);
|
||||
|
||||
return {
|
||||
send: connection.send,
|
||||
send(action: string, data: Object = {}) {
|
||||
if('sessionToken' in data) {
|
||||
console.warn('sessionToken already present in action. this is deprecated.')
|
||||
console.trace();
|
||||
}
|
||||
connection.send(action, {
|
||||
...(data ?? {}),
|
||||
sessionToken
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
import { CgHashtag } from "react-icons/cg";
|
||||
import useChannel from "../hooks/useChannel";
|
||||
import useHover from "../hooks/useHover";
|
||||
|
||||
interface ChannelProps {
|
||||
unread: number;
|
||||
uid: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export default function Channel(props: ChannelProps) {
|
||||
const { channel, setChannel } = useChannel();
|
||||
const { unread, uid, name } = props;
|
||||
const [ref, hover] = useHover<HTMLDivElement>();
|
||||
const selected = channel === uid;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
margin: '2px 2px',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'min-content 1fr',
|
||||
color: selected ? 'cyan' : 'inherit',
|
||||
cursor: 'pointer',
|
||||
background: selected ? 'var(--current-line)' :
|
||||
hover ? 'rgba(255, 255, 255, 0.1)' :
|
||||
'inherit',
|
||||
borderRadius: '8px',
|
||||
// placeItems: 'left center',
|
||||
// border: '1px solid white'
|
||||
}}
|
||||
onClick={() => {
|
||||
setChannel(uid);
|
||||
}}
|
||||
ref={ref}
|
||||
>
|
||||
<CgHashtag color={
|
||||
selected ? 'var(--foreground)' :
|
||||
hover ? 'var(--comment)' :
|
||||
'var(--current-line)'
|
||||
} size={24} style={{
|
||||
fontWeight: 'bold',
|
||||
margin: '4px',
|
||||
}}></CgHashtag>
|
||||
<div style={{
|
||||
lineHeight: '32px',
|
||||
color: selected ? 'var(--foreground)' :
|
||||
hover ? 'var(--comment)' :
|
||||
'var(--current-line)'
|
||||
}}>
|
||||
{name.toLowerCase().replaceAll(' ', '-').trim()}
|
||||
</div>
|
||||
{/* {(unread > 0) && (
|
||||
<span style={{ paddingRight: '8px' }}>({unread})</span>
|
||||
)}
|
||||
<span style={{
|
||||
fontWeight: (unread ?? 0) > 0 ? 'bold' : '300',
|
||||
}}>
|
||||
{name}
|
||||
</span>
|
||||
<a style={{
|
||||
color: 'rgba(0, 100, 200, 1)',
|
||||
marginLeft: '8px',
|
||||
fontSize: '10px',
|
||||
}} href="#" onClick={() => {}}>Delete</a> */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -9,20 +9,13 @@ import useClientId from '../hooks/useClientId';
|
|||
import useHomeServer from '../contexts/PersistentState/useHomeServerNative';
|
||||
import Logout from '../components/Logout';
|
||||
import { CgHashtag } from 'react-icons/cg';
|
||||
import Channel from './Channel';
|
||||
|
||||
interface IChannel {
|
||||
uid: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
function Hashmark() {
|
||||
return <CgHashtag style={{
|
||||
fontWeight: 'bold',
|
||||
marginRight: '8px',
|
||||
marginLeft: '8px',
|
||||
}}>#</CgHashtag>;
|
||||
}
|
||||
|
||||
interface IUnreads {
|
||||
[uid: string]: number
|
||||
}
|
||||
|
|
@ -81,7 +74,7 @@ export default function Channels() {
|
|||
|
||||
useEffect(() => {
|
||||
if(clientId === null) return;
|
||||
send('client:get', clientId);
|
||||
send('client:get', { clientId });
|
||||
}, [clientId]);
|
||||
|
||||
const textbox = useRef<HTMLInputElement>(null);
|
||||
|
|
@ -99,30 +92,14 @@ export default function Channels() {
|
|||
}}>
|
||||
<br></br>
|
||||
{channels.map(c => (
|
||||
<div key={c.uid} style={{
|
||||
margin: '8px 0px',
|
||||
color: channel === c.uid ? 'cyan' : 'inherit',
|
||||
cursor: 'pointer',
|
||||
}} onClick={() => {
|
||||
setChannel(c.uid);
|
||||
}}>
|
||||
<Hashmark></Hashmark>
|
||||
{(c.uid in unreads) && (unreads[c.uid] > 0) && (
|
||||
<span style={{ paddingRight: '8px' }}>({unreads[c.uid]})</span>
|
||||
)}
|
||||
<span style={{
|
||||
fontWeight: (unreads[c.uid] ?? 0) > 0 ? 'bold' : '300',
|
||||
}}>
|
||||
{c.name}
|
||||
</span>
|
||||
<a style={{
|
||||
color: 'rgba(0, 100, 200, 1)',
|
||||
marginLeft: '8px',
|
||||
fontSize: '10px',
|
||||
}} href="#" onClick={() => {}}>Delete</a>
|
||||
</div>
|
||||
<Channel
|
||||
key={c.uid}
|
||||
uid={c.uid}
|
||||
unread={unreads[c.uid] ?? 0}
|
||||
name={c.name}
|
||||
></Channel>
|
||||
))}
|
||||
<Hashmark></Hashmark><input
|
||||
{/* <input
|
||||
ref={textbox}
|
||||
style={{
|
||||
background: '#343746',
|
||||
|
|
@ -146,7 +123,7 @@ export default function Channels() {
|
|||
// lineHeight: '20px'
|
||||
}}>ADD</button>
|
||||
<NameTextbox></NameTextbox><br></br>
|
||||
<Logout></Logout><br></br>
|
||||
<Logout></Logout><br></br> */}
|
||||
{/* <LoginQR></LoginQR> */}
|
||||
{/* <Totp></Totp> */}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export default () => {
|
|||
}, [messages]);
|
||||
|
||||
useEffect(() => {
|
||||
send('message:recent', { channel, sessionToken });
|
||||
send('message:recent', { channel });
|
||||
}, [channel, sessionToken]);
|
||||
|
||||
const sendMessage = useCallback(() => {
|
||||
|
|
@ -54,11 +54,11 @@ export default () => {
|
|||
if(sessionToken === null) return;
|
||||
send(
|
||||
'message:message',
|
||||
{ ...createMessage(
|
||||
createMessage(
|
||||
clientId,
|
||||
textBoxRef.current.innerText,
|
||||
channel,
|
||||
), sessionToken },
|
||||
)
|
||||
);
|
||||
textBoxRef.current.innerText = '';
|
||||
}, [channel, sessionToken]);
|
||||
|
|
@ -143,9 +143,11 @@ export default () => {
|
|||
cursor: 'pointer',
|
||||
display: 'grid',
|
||||
placeItems: 'center center',
|
||||
fontSize: '32px',
|
||||
paddingLeft: '4px',
|
||||
// paddingTop: '2px',
|
||||
boxSizing: 'border-box',
|
||||
}}>
|
||||
<MdSend></MdSend>
|
||||
<MdSend size={24}></MdSend>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ export default function NameTextbox() {
|
|||
const [inputElement, setInputElement] = useState<HTMLInputElement | null>(null);
|
||||
|
||||
const { send } = useApi({
|
||||
'client:get'(_name: string) {
|
||||
setName(_name);
|
||||
'client:get'(data: any) {
|
||||
setName(data.name);
|
||||
},
|
||||
}, [name, clientId]);
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ export default function NameTextbox() {
|
|||
useEffect(() => {
|
||||
if(clientId === null) return;
|
||||
if(inputElement === null) return;
|
||||
send('client:get', clientId);
|
||||
send('client:get', { clientId });
|
||||
}, [inputElement, clientId]);
|
||||
|
||||
return <input
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
DB_HOST=localhost
|
||||
DB_USER=corner
|
||||
DB_PASSWORD=corner
|
||||
DB_DB=corner
|
||||
DB_DB=corner
|
||||
|
|
|
|||
|
|
@ -46,6 +46,12 @@ const migrationConnection = createConnection({
|
|||
multipleStatements: true,
|
||||
});
|
||||
|
||||
function keepAlive() {
|
||||
connection.ping();
|
||||
migrationConnection.ping();
|
||||
}
|
||||
setInterval(keepAlive, 60000); // ping to DB every minute
|
||||
|
||||
const connected: Promise<null> = new Promise((res, rej) => {
|
||||
migrationConnection.connect((err) => {
|
||||
if(err === null) {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
SELECT name FROM clients WHERE uid=?
|
||||
SELECT name, username, uid FROM clients WHERE uid=?
|
||||
|
|
@ -25,6 +25,9 @@ export function expose(router: Function, port: number) {
|
|||
if(auth === null) return;
|
||||
data.$clientId = auth;
|
||||
}
|
||||
if(typeof data !== 'object') {
|
||||
throw new Error('action ' + action + ' payload not an object');
|
||||
}
|
||||
console.log('[IN]', action, data);
|
||||
const _return = await (router(action, data) as unknown as Promise<any>);
|
||||
if(_return) {
|
||||
|
|
|
|||
|
|
@ -16,10 +16,14 @@ export default router({
|
|||
if(response === null) return;
|
||||
return reply(response[0][0].uid);
|
||||
},
|
||||
async 'get'(uid: string) {
|
||||
const response = await query(_get, uid);
|
||||
async 'get'(data: any) {
|
||||
const response = await query(_get, data.clientId);
|
||||
if(response === null) return;
|
||||
return reply(response[0].name);
|
||||
return reply({
|
||||
name: response[0].name,
|
||||
clientId: response[0].uid,
|
||||
username: response[0].username
|
||||
});
|
||||
},
|
||||
async 'rename'(data: any) {
|
||||
const { clientId, name } = data;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ export default router({
|
|||
});
|
||||
|
||||
export async function validateSessionToken(token: string) {
|
||||
console.log('ASDASDASDASD')
|
||||
const res = await query(_get, token);
|
||||
if(res === null) return null;
|
||||
if(res.length === 1 && res[0].expires > Date.now())
|
||||
|
|
|
|||
Reference in New Issue