mirror of
https://github.com/urbit/shrub.git
synced 2024-11-30 22:15:47 +03:00
ux: show a keypress indicator after a delay
This commit is contained in:
parent
d7ec69803f
commit
8d0ca32c5d
@ -145,7 +145,7 @@ const onInput = (name: string, session: Session, e: string) => {
|
||||
}
|
||||
const term = session.term;
|
||||
const belts = readInput(term, e);
|
||||
belts.map((b) => {
|
||||
belts.forEach((b) => {
|
||||
useTermState.getState().set((state) => {
|
||||
state.sessions[name].pending++;
|
||||
});
|
||||
|
59
pkg/interface/webterm/Spinner.tsx
Normal file
59
pkg/interface/webterm/Spinner.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import useIsMounted from './lib/useIsMounted';
|
||||
import React from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
// TODO: Tune these values
|
||||
const DELAY_MS = 1000;
|
||||
const FRAME_MS = 200;
|
||||
// Some alternative ASCII spinners:
|
||||
// https://stackoverflow.com/questions/2685435/cooler-ascii-spinners
|
||||
// const CHARS = '⣾⣽⣻⢿⡿⣟⣯⣷';
|
||||
const CHARS = '◴◷◶◵';
|
||||
|
||||
const Spinner = () => {
|
||||
const [index, setIndex] = useState(0);
|
||||
const [intervalTimer, setIntervalTimer] = useState<ReturnType<typeof setInterval> | undefined>();
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
useEffect(() => {
|
||||
setIntervalTimer(
|
||||
setInterval(() => {
|
||||
if (isMounted()) {
|
||||
setIndex(idx => idx === CHARS.length - 1 ? 0 : idx + 1);
|
||||
}
|
||||
}, FRAME_MS)
|
||||
);
|
||||
|
||||
return () => {
|
||||
if (intervalTimer) {
|
||||
clearInterval(intervalTimer);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return <span> {CHARS[index]}</span>;
|
||||
};
|
||||
|
||||
export const DelayedSpinner = () => {
|
||||
const [showSpinner, setShowSpinner] = useState(false);
|
||||
const [delayTimer, setDelayTimer] = useState<ReturnType<typeof setTimeout> | undefined>();
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
useEffect(() => {
|
||||
setDelayTimer(
|
||||
setTimeout(() => {
|
||||
if (isMounted()) {
|
||||
setShowSpinner(true);
|
||||
}
|
||||
}, DELAY_MS)
|
||||
);
|
||||
|
||||
return () => {
|
||||
if (delayTimer) {
|
||||
clearTimeout(delayTimer);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return showSpinner ? <Spinner /> : null;
|
||||
};
|
@ -1,8 +1,9 @@
|
||||
import { DEFAULT_SESSION } from './constants';
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import useTermState, { Session } from './state';
|
||||
import api from './api';
|
||||
import { pokeTask } from '@urbit/api/term';
|
||||
import { DelayedSpinner as Spinner } from './Spinner';
|
||||
|
||||
interface TabProps {
|
||||
session: Session;
|
||||
@ -40,12 +41,19 @@ export const Tab = ( { session, name }: TabProps ) => {
|
||||
});
|
||||
}, [session]);
|
||||
|
||||
// TODO: sometimes the pending is not decremented?
|
||||
useEffect(() => {
|
||||
if(session) {
|
||||
console.log(`${session.subscriptionId}: ${session.pending} pending`);
|
||||
}
|
||||
}, [session]);
|
||||
|
||||
return (
|
||||
<div className={'tab ' + (isSelected ? 'selected' : '')} onClick={onClick}>
|
||||
<a className='session-name'>
|
||||
{session?.hasBell ? '🔔 ' : ''}
|
||||
{name === DEFAULT_SESSION ? 'default' : name}
|
||||
{session && session.pending > 0 ? ' o' : ''}
|
||||
{session && session.pending > 0 ? <Spinner /> : null}
|
||||
{' '}
|
||||
</a>
|
||||
{name === DEFAULT_SESSION ? null : <a className="delete-session" onClick={onDelete}>x</a>}
|
||||
|
17
pkg/interface/webterm/lib/useIsMounted.ts
Normal file
17
pkg/interface/webterm/lib/useIsMounted.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
|
||||
function useIsMounted() {
|
||||
const isMounted = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
isMounted.current = true;
|
||||
|
||||
return () => {
|
||||
isMounted.current = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return useCallback(() => isMounted.current, []);
|
||||
}
|
||||
|
||||
export default useIsMounted;
|
Loading…
Reference in New Issue
Block a user