recoil#useResetRecoilState TypeScript Examples
The following examples show how to use
recoil#useResetRecoilState.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: gridLibraryContext.ts From frames with Mozilla Public License 2.0 | 6 votes |
useGridReset = () => {
const type = useResetRecoilState(GridTypeAtom);
const value = useResetRecoilState(GridValueAtom);
return () => {
type();
value();
}
}
Example #2
Source File: survey-list.tsx From clean-react with GNU General Public License v3.0 | 6 votes |
SurveyList: React.FC<Props> = ({ loadSurveyList }: Props) => {
const resetSurveyListState = useResetRecoilState(surveyListState)
const handleError = useErrorHandler((error: Error) => {
setState(old => ({ ...old, error: error.message }))
})
const [state, setState] = useRecoilState(surveyListState)
const reload = (): void => setState(old => ({ surveys: [], error: '', reload: !old.reload }))
useEffect(() => resetSurveyListState(), [])
useEffect(() => {
loadSurveyList.loadAll()
.then(surveys => setState(old => ({ ...old, surveys })))
.catch(handleError)
}, [state.reload])
return (
<div className={Styles.surveyListWrap}>
<Header />
<div className={Styles.contentWrap}>
<h2>Enquetes</h2>
{state.error
? <Error error={state.error} reload={reload} />
: <SurveyListItem surveys={state.surveys} />
}
</div>
<Footer />
</div>
)
}
Example #3
Source File: ErrorPopup.tsx From nextclade with MIT License | 6 votes |
export function ErrorPopup() {
const { t } = useTranslationSafe()
const error = useRecoilValue(globalErrorAtom)
const dismissError = useResetRecoilState(globalErrorAtom)
const reload = useReloadPage('/')
if (!error) {
return null
}
return (
<Modal centered isOpen backdrop="static" toggle={dismissError} fade={false} size="lg">
<ModalHeader toggle={dismissError} tag="div">
<h3 className="text-center text-danger">{t('Error')}</h3>
</ModalHeader>
<ModalBody>
<ErrorContent error={error} />
<ErrorContentExplanation />
</ModalBody>
<ModalFooter>
<div className="ml-auto">
<Button type="button" color="danger" title={t('Reload the page and start Nextclade fresh')} onClick={reload}>
{t('Restart Nextclade')}
</Button>
<ButtonOk type="button" color="secondary" title={t('Close this dialog window')} onClick={dismissError}>
{t('Dismiss')}
</ButtonOk>
</div>
</ModalFooter>
</Modal>
)
}
Example #4
Source File: opacityScroll.ts From frames with Mozilla Public License 2.0 | 6 votes |
export default function useOnScroll() {
const [reference, setReference] = useRecoilState(OnScrollReference);
const setStart = useSetRecoilState(StartRefHeight);
const setCurrent = useSetRecoilState(CurrentRefHeight);
const values = useRecoilValue(OpacitySelector);
const setNavOpacity = useSetRecoilState(NavOpacityAtom);
const refReset = useResetRecoilState(OnScrollReference);
const currentReset = useResetRecoilState(CurrentRefHeight);
const startRefReset = useResetRecoilState(StartRefHeight);
const onScroll = () => {
const currentHeight = reference?.getBoundingClientRect().top;
setCurrent(currentHeight);
}
useEffect(() => {
setNavOpacity((values.height < 0.5 ? 1.3: 0.9) - values.height);
}, [values])
const reset = () => {
refReset();
currentReset();
startRefReset();
}
useEffect(() => {
const height = reference?.getBoundingClientRect().top;
setStart(height);
}, [reference])
return {reset, values, setReference, onScroll};
}
Example #5
Source File: infoContext.ts From frames with Mozilla Public License 2.0 | 6 votes |
resetInfo = () => {
const trailer = useResetRecoilState(infoTrailerContext);
const season = useResetRecoilState(InfoSeasonsContext);
const media = useResetRecoilState(InfoMediaIdContext);
const section = useResetRecoilState(InfoSectionContext);
const sections = useResetRecoilState(InfoSectionsContext);
return () => {
trailer();
section();
season();
media();
sections();
}
}
Example #6
Source File: homeContext.tsx From frames with Mozilla Public License 2.0 | 6 votes |
export function useReset() {
const pGraph = useResetRecoilState(pGraphAtom);
const image = useResetRecoilState(imageAtom);
const section = useResetRecoilState(sectionAtom);
const sHeight = useResetRecoilState(startHeight);
const trailer = useResetRecoilState(TrailerAtom);
const cb = useResetRecoilState(CurrentBanner);
return () => {
cb();
trailer();
sHeight();
section();
image();
pGraph();
}
}
Example #7
Source File: gridLibraryContext.ts From frames with Mozilla Public License 2.0 | 6 votes |
useGridReset = () => {
const type = useResetRecoilState(GridTypeAtom);
const value = useResetRecoilState(GridValueAtom);
const onScreen = useResetRecoilState(GridOnScreenAtom);
return () => {
type();
value();
onScreen();
}
}
Example #8
Source File: authContext.ts From frames with Mozilla Public License 2.0 | 6 votes |
useReset = () => {
const error = useResetRecoilState(AuthContextErrorAtom);
const process = useResetRecoilState(AuthContextProcessAtom);
const email = useResetRecoilState(AuthContextEmailAtom);
const password = useResetRecoilState(AuthContextPasswordAtom);
const fade = useResetRecoilState(AuthFade);
const authKey = useResetRecoilState(AuthKeyAtom);
const picker = useResetRecoilState(AuthPicker);
const auth = useResetRecoilState(Authenticated);
return () => {
auth();
error();
process();
email();
password();
fade();
authKey();
picker();
}
}
Example #9
Source File: editPicks.tsx From frames with Mozilla Public License 2.0 | 6 votes |
function useReset() {
const media = useResetRecoilState(PickMediaAtom);
const search = useResetRecoilState(SearchPickAtom);
const active = useResetRecoilState(PickActiveAtom);
const display = useResetRecoilState(PickDisplayAtom);
const category = useResetRecoilState(PickCategoryAtom);
const type = useResetRecoilState(PickTypeAtom);
return () => {
media();
search();
active();
display();
category();
type();
}
}
Example #10
Source File: editMedia.tsx From frames with Mozilla Public License 2.0 | 6 votes |
useReset = () => {
const tmdb = useResetRecoilState(TmdbAtom);
const logo = useResetRecoilState(LogoAtom);
const backdrop = useResetRecoilState(BackdropAtom);
const name = useResetRecoilState(NameAtom);
const poster = useResetRecoilState(PosterAtom);
const type = useResetRecoilState(TypeAtom);
const location = useResetRecoilState(LocationAtom);
const found = useResetRecoilState(FoundAtom);
return () => {
type();
tmdb();
location();
logo();
backdrop();
name();
poster();
found();
}
}
Example #11
Source File: opacityScroll.ts From frames with Mozilla Public License 2.0 | 6 votes |
export default function useOnScroll() {
const [reference, setReference] = useRecoilState(OnScrollReference);
const setStart = useSetRecoilState(StartRefHeight);
const setCurrent = useSetRecoilState(CurrentRefHeight);
const values = useRecoilValue(OpacitySelector);
const setNavOpacity = useSetRecoilState(NavOpacityAtom);
const refReset = useResetRecoilState(OnScrollReference);
const currentReset = useResetRecoilState(CurrentRefHeight);
const startRefReset = useResetRecoilState(StartRefHeight);
const onScroll = () => {
const currentHeight = reference?.getBoundingClientRect().top;
setCurrent(currentHeight);
}
useEffect(() => {
setNavOpacity((values.height < 0.5 ? 1.3: 0.9) - values.height);
}, [values])
const reset = () => {
refReset();
currentReset();
startRefReset();
}
useEffect(() => {
const height = reference?.getBoundingClientRect().top;
setStart(height);
}, [reference])
return {reset, values, setReference, onScroll, navDark: values.lowOpacity > 0.7};
}
Example #12
Source File: authContext.ts From frames with Mozilla Public License 2.0 | 6 votes |
useReset = () => {
const error = useResetRecoilState(AuthContextErrorAtom);
const process = useResetRecoilState(AuthContextProcessAtom);
const email = useResetRecoilState(AuthContextEmailAtom);
const password = useResetRecoilState(AuthContextPasswordAtom);
const fade = useResetRecoilState(AuthFade);
const authKey = useResetRecoilState(AuthKeyAtom);
const auth = useResetRecoilState(Authenticated);
return () => {
auth();
error();
process();
email();
password();
fade();
authKey();
}
}
Example #13
Source File: navbar.tsx From frames with Mozilla Public License 2.0 | 6 votes |
function Sections() {
const navContext = useRecoilValue(NavConTextAtom);
const sections = ["home", "movies", "tv shows", "playlists", "collections"];
const paths = ["/", "/movies", "/shows", "/playlist", "/collections"];
const resetSearch = useResetRecoilState(SearchContextAtom);
const reset = () => {
resetSearch();
};
return (
<div className={styles.navSections} onClick={reset}>
{sections.map((item, v) => {
return (
<Link key={v} href={paths[v]}>
<span
className={item === navContext ? styles.activeSection : styles.passiveSections}>{item}</span>
</Link>
);
})}
</div>
);
}
Example #14
Source File: infoContext.ts From frames with Mozilla Public License 2.0 | 6 votes |
resetInfo = () => {
const season = useResetRecoilState(InfoSeasonsContext);
const media = useResetRecoilState(InfoMediaIdContext);
const section = useResetRecoilState(InfoSectionContext);
const sections = useResetRecoilState(InfoSectionsContext);
const info = useResetRecoilState(infoUserContext);
return () => {
section();
season();
media();
sections();
info();
}
}
Example #15
Source File: homeContext.tsx From frames with Mozilla Public License 2.0 | 6 votes |
export function useReset() {
const pGraph = useResetRecoilState(pGraphAtom);
const image = useResetRecoilState(imageAtom);
const section = useResetRecoilState(sectionAtom);
const sHeight = useResetRecoilState(startHeight);
return () => {
sHeight();
section();
image();
pGraph();
}
}
Example #16
Source File: playback.ts From frames with Mozilla Public License 2.0 | 5 votes |
cleanUp = () => {
const {user, signOut} = useUser();
const response = useRecoilValue(framesVideoStateAtom);
const fullscreenReset = useResetRecoilState(fullscreenAddressAtom);
const framesVideoStateReset = useResetRecoilState(framesVideoStateAtom);
const currentReset = useResetRecoilState(currentDuration);
const framesReset = useResetRecoilState(framesPlayer);
const framesPlayerStateReset = useResetRecoilState(framesPlayerStateAtom);
const volumeFrameReset = useResetRecoilState(volumeFrameAtom);
const displayReset = useResetRecoilState(displaySidesAtom);
const shareAndDownloadReset = useResetRecoilState(shareAndDownloadAtom);
const PipAndFullscreenReset = useResetRecoilState(PipAndFullscreenAtom);
const SubtitlesAndUpNextReset = useResetRecoilState(SubtitlesAndUpNextAtom);
const UpNextReset = useResetRecoilState(UpNextAtom);
const HideImageReset = useResetRecoilState(HideImageAtom);
const framesSubtitlesReset = useResetRecoilState(framesSubtitlesAtom);
const SubtitlesSyncReset = useResetRecoilState(SubtitlesSyncAtom);
const FramesPlayerErrorReset = useResetRecoilState(FramesPlayerErrorAtom);
const CastEventReset = useResetRecoilState(CastEventAtom);
const CastStateReset = useResetRecoilState(VideoStateAtom);
const AirplayReset = useResetRecoilState(AirplayAtom);
const alreadyStreamingReset = useResetRecoilState(AlreadyStreamingAtom);
const {channel} = useGroupWatch();
const {globalChannel} = useNotification();
return () => {
channel.modifyPresenceState('online');
globalChannel.modifyPresenceState('online');
fetch('/api/stream/verifyStream?action=done');
if (user?.role === Role.GUEST && response?.frame)
signOut();
fullscreenReset();
framesVideoStateReset();
currentReset();
framesReset();
framesPlayerStateReset();
volumeFrameReset();
displayReset();
shareAndDownloadReset();
PipAndFullscreenReset();
SubtitlesAndUpNextReset();
UpNextReset();
HideImageReset();
framesSubtitlesReset();
SubtitlesSyncReset();
FramesPlayerErrorReset();
CastEventReset();
CastStateReset();
AirplayReset();
alreadyStreamingReset();
}
}
Example #17
Source File: survey-result.tsx From clean-react with GNU General Public License v3.0 | 5 votes |
SurveyResult: React.FC<Props> = ({ loadSurveyResult, saveSurveyResult }: Props) => {
const resetSurveyResultState = useResetRecoilState(surveyResultState)
const handleError = useErrorHandler((error: Error) => {
setState(old => ({ ...old, surveyResult: null, isLoading: false, error: error.message }))
})
const [state, setState] = useRecoilState(surveyResultState)
const setOnAnswer = useSetRecoilState(onSurveyAnswerState)
const onAnswer = (answer: string): void => {
if (!state.isLoading) {
setState(old => ({ ...old, isLoading: true }))
saveSurveyResult.save({ answer })
.then(surveyResult => setState(old => ({ ...old, isLoading: false, surveyResult })))
.catch(handleError)
}
}
const reload = (): void => setState(old => ({ ...old, error: '', reload: !old.reload }))
useEffect(() => {
resetSurveyResultState()
setOnAnswer({ onAnswer })
}, [])
useEffect(() => {
loadSurveyResult.load()
.then(surveyResult => setState(old => ({ ...old, surveyResult })))
.catch(handleError)
}, [state.reload])
return (
<div className={Styles.surveyResultWrap}>
<Header />
<div data-testid="survey-result" className={Styles.contentWrap}>
{state.surveyResult && <SurveyResultData surveyResult={state.surveyResult} /> }
{state.isLoading && <Loading />}
{state.error && <Error error={state.error} reload={reload} />}
</div>
<Footer />
</div>
)
}
Example #18
Source File: signup.tsx From clean-react with GNU General Public License v3.0 | 5 votes |
SignUp: React.FC<Props> = ({ validation, addAccount }: Props) => {
const resetSignUpState = useResetRecoilState(signUpState)
const { setCurrentAccount } = useRecoilValue(currentAccountState)
const history = useHistory()
const [state, setState] = useRecoilState(signUpState)
useEffect(() => resetSignUpState(), [])
useEffect(() => validate('name'), [state.name])
useEffect(() => validate('email'), [state.email])
useEffect(() => validate('password'), [state.password])
useEffect(() => validate('passwordConfirmation'), [state.passwordConfirmation])
const validate = (field: string): void => {
const { name, email, password, passwordConfirmation } = state
const formData = { name, email, password, passwordConfirmation }
setState(old => ({ ...old, [`${field}Error`]: validation.validate(field, formData) }))
setState(old => ({ ...old, isFormInvalid: !!old.nameError || !!old.emailError || !!old.passwordError || !!old.passwordConfirmationError }))
}
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>): Promise<void> => {
event.preventDefault()
try {
if (state.isLoading || state.isFormInvalid) {
return
}
setState(old => ({ ...old, isLoading: true }))
const account = await addAccount.add({
name: state.name,
email: state.email,
password: state.password,
passwordConfirmation: state.passwordConfirmation
})
setCurrentAccount(account)
history.replace('/')
} catch (error) {
setState(old => ({
...old,
isLoading: false,
mainError: error.message
}))
}
}
return (
<div className={Styles.signupWrap}>
<LoginHeader />
<form data-testid="form" className={Styles.form} onSubmit={handleSubmit}>
<h2>Criar Conta</h2>
<Input type="text" name="name" placeholder="Digite seu nome" />
<Input type="email" name="email" placeholder="Digite seu e-mail" />
<Input type="password" name="password" placeholder="Digite sua senha" />
<Input type="password" name="passwordConfirmation" placeholder="Repita sua senha" />
<SubmitButton text="Cadastrar" />
<Link data-testid="login-link" replace to="/login" className={Styles.link}>Voltar Para Login</Link>
<FormStatus />
</form>
<Footer />
</div>
)
}
Example #19
Source File: login.tsx From clean-react with GNU General Public License v3.0 | 5 votes |
Login: React.FC<Props> = ({ validation, authentication }: Props) => {
const resetLoginState = useResetRecoilState(loginState)
const { setCurrentAccount } = useRecoilValue(currentAccountState)
const history = useHistory()
const [state, setState] = useRecoilState(loginState)
useEffect(() => resetLoginState(), [])
useEffect(() => validate('email'), [state.email])
useEffect(() => validate('password'), [state.password])
const validate = (field: string): void => {
const { email, password } = state
const formData = { email, password }
setState(old => ({ ...old, [`${field}Error`]: validation.validate(field, formData) }))
setState(old => ({ ...old, isFormInvalid: !!old.emailError || !!old.passwordError }))
}
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>): Promise<void> => {
event.preventDefault()
try {
if (state.isLoading || state.isFormInvalid) {
return
}
setState(old => ({ ...old, isLoading: true }))
const account = await authentication.auth({
email: state.email,
password: state.password
})
setCurrentAccount(account)
history.replace('/')
} catch (error) {
setState(old => ({
...old,
isLoading: false,
mainError: error.message
}))
}
}
return (
<div className={Styles.loginWrap}>
<LoginHeader />
<form data-testid="form" className={Styles.form} onSubmit={handleSubmit}>
<h2>Login</h2>
<Input type="email" name="email" placeholder="Digite seu e-mail" />
<Input type="password" name="password" placeholder="Digite sua senha" />
<SubmitButton text="Entrar" />
<Link data-testid="signup-link" to="/signup" className={Styles.link}>Criar conta</Link>
<FormStatus />
</form>
<Footer />
</div>
)
}
Example #20
Source File: SettingsActions.tsx From phosphor-home with MIT License | 5 votes |
SettingsActions: React.FC = () => {
const weight = useRecoilValue(iconWeightAtom);
const size = useRecoilValue(iconSizeAtom);
const color = useRecoilValue(iconColorAtom);
const reset = useResetRecoilState(resetSettingsSelector);
const [copied, setCopied] = useTransientState<boolean>(false, 2000);
const copyDeepLinkToClipboard = () => {
const paramString = new URLSearchParams([
["weight", weight.toString()],
["size", size.toString()],
["color", color.replace("#", "")],
]).toString();
void navigator.clipboard
?.writeText(`${window.location.host}?${paramString}`)
.then(() => {
setCopied(true);
})
.catch(() => {
alert("Clipboard permissions must be enabled to copy links!");
});
};
return (
<>
<button
className="action-button"
title="Restore default settings"
onClick={reset}
>
<ArrowCounterClockwise size={24} />
</button>
<button
className="action-button"
title="Copy URL for current settings"
onClick={copyDeepLinkToClipboard}
>
{copied ? (
<CheckCircle size={24} color="#1FA647" weight="fill" />
) : (
<Link size={24} />
)}
</button>
</>
);
}
Example #21
Source File: DatasetCurrent.tsx From nextclade with MIT License | 5 votes |
export function DatasetCurrent() {
const { t } = useTranslationSafe()
const [advancedOpen, setAdvancedOpen] = useState(false)
const datasetCurrent = useRecoilValue(datasetCurrentAtom)
const resetDatasetCurrent = useResetRecoilState(datasetCurrentNameAtom)
const onChangeClicked = useCallback(() => {
resetDatasetCurrent()
}, [resetDatasetCurrent])
const onCustomizeClicked = useCallback(() => setAdvancedOpen((advancedOpen) => !advancedOpen), [])
if (!datasetCurrent) {
return null
}
return (
<CurrentDatasetInfoContainer>
<CurrentDatasetInfoHeader>
<DatasetInfoH4>{t('Selected pathogen')}</DatasetInfoH4>
</CurrentDatasetInfoHeader>
<CurrentDatasetInfoBody>
<Row noGutters>
<Col className="d-flex flex-row">
<Left>
<DatasetInfo dataset={datasetCurrent} />
</Left>
<Right>
<ChangeButton type="button" color="secondary" onClick={onChangeClicked}>
{t('Change')}
</ChangeButton>
<LinkExternal
className="ml-auto mt-auto"
href="https://github.com/nextstrain/nextclade_data/blob/master/CHANGELOG.md"
>
<small>{t('Recent dataset updates')}</small>
</LinkExternal>
</Right>
</Col>
</Row>
<Row noGutters>
<Col>
<ButtonCustomize isOpen={advancedOpen} onClick={onCustomizeClicked} />
<Collapse isOpen={advancedOpen}>
<AdvancedModeExplanationWrapper>
<AdvancedModeExplanationContent />
</AdvancedModeExplanationWrapper>
<FilePickerAdvanced />
</Collapse>
</Col>
</Row>
</CurrentDatasetInfoBody>
</CurrentDatasetInfoContainer>
)
}
Example #22
Source File: FramesStates.tsx From frames with Mozilla Public License 2.0 | 5 votes |
resetFrames = () => {
const aSubs = useResetRecoilState(moveSubsAtom);
const bSubs = useResetRecoilState(framesSubtitles);
const cSubs = useResetRecoilState(subOverAtom);
const dSubs = useResetRecoilState(displaySidesAtom);
const eSubs = useResetRecoilState(displayInfoAtom);
const fSubs = useResetRecoilState(playVideoAtom);
const gSubs = useResetRecoilState(framesPlayer);
const hSubs = useResetRecoilState(bufferingAtom);
const iSubs = useResetRecoilState(volumeAtom);
const jSubs = useResetRecoilState(mutedAtom);
const kSubs = useResetRecoilState(activeSubs);
const lSubs = useResetRecoilState(UpNextURL);
const mSubs = useResetRecoilState(nextOver);
const nSubs = useResetRecoilState(nextHolder);
const oSubs = useResetRecoilState(currentDuration);
const pOver = useResetRecoilState(shareOver);
const qOver = useResetRecoilState(CastEventAtom);
const rOver = useResetRecoilState(VideoStateAtom);
const sOver = useResetRecoilState(differance);
const uOver = useResetRecoilState(GWMOver);
const vOver = useResetRecoilState(DownOver);
return () => {
aSubs();
bSubs();
cSubs();
dSubs();
eSubs();
fSubs();
gSubs();
hSubs();
iSubs();
jSubs();
kSubs();
lSubs();
pOver();
mSubs();
nSubs();
oSubs();
qOver();
rOver();
sOver();
uOver();
vOver();
}
}
Example #23
Source File: MainInputFormSequenceFilePicker.tsx From nextclade with MIT License | 4 votes |
export function MainInputFormSequenceFilePicker() {
const { t } = useTranslationSafe()
const datasetCurrent = useRecoilValue(datasetCurrentAtom)
const [qrySeq, setQrySeq] = useRecoilState(qrySeqInputAtom)
const removeQrySeq = useResetRecoilState(qrySeqInputAtom)
const qrySeqError = useRecoilValue(qrySeqErrorAtom)
const canRun = useRecoilValue(canRunAtom)
const [shouldRunAutomatically, setShouldRunAutomatically] = useRecoilState(shouldRunAutomaticallyAtom)
const hasRequiredInputs = useRecoilValue(hasRequiredInputsAtom)
const hasInputErrors = useRecoilValue(hasInputErrorsAtom)
const icon = useMemo(() => <FileIconFasta />, [])
const run = useRunAnalysis()
const setSequences = useCallback(
(input: AlgorithmInput) => {
setQrySeq(input)
if (shouldRunAutomatically) {
run()
}
},
[run, setQrySeq, shouldRunAutomatically],
)
const setExampleSequences = useCallback(() => {
if (datasetCurrent) {
setQrySeq(new AlgorithmInputDefault(datasetCurrent))
if (shouldRunAutomatically) {
run()
}
}
}, [datasetCurrent, run, setQrySeq, shouldRunAutomatically])
const { isRunButtonDisabled, runButtonColor, runButtonTooltip } = useMemo(() => {
const isRunButtonDisabled = !(canRun && hasRequiredInputs) || hasInputErrors
return {
isRunButtonDisabled,
runButtonColor: isRunButtonDisabled ? 'secondary' : 'success',
runButtonTooltip: isRunButtonDisabled
? t('Please provide input files for the algorithm')
: t('Launch the algorithm!'),
}
}, [canRun, hasInputErrors, hasRequiredInputs, t])
const LoadExampleLink = useMemo(() => {
const cannotLoadExample = hasRequiredInputs || hasInputErrors || !datasetCurrent
return (
<Button color="link" onClick={setExampleSequences} disabled={cannotLoadExample}>
{t('Load example')}
</Button>
)
}, [datasetCurrent, hasInputErrors, hasRequiredInputs, setExampleSequences, t])
const onToggleRunAutomatically = useCallback(() => {
setShouldRunAutomatically((shouldRunAutomatically) => !shouldRunAutomatically)
}, [setShouldRunAutomatically])
return (
<SequenceFilePickerContainer>
<FilePicker
title={t('Provide sequence data')}
icon={icon}
exampleUrl="https://example.com/sequences.fasta"
pasteInstructions={t('Enter sequence data in FASTA or plain text format')}
input={qrySeq}
error={qrySeqError}
isInProgress={false}
onRemove={removeQrySeq}
onInput={setSequences}
/>
<Row noGutters className="mt-2">
<Col className="w-100 d-flex">
<FlexLeft>
<Form className="d-flex h-100 mt-1">
<FormGroup className="my-auto">
<Toggle
identifier="toggle-run-automatically"
checked={shouldRunAutomatically}
onCheckedChanged={onToggleRunAutomatically}
>
<span title="Run Nextclade automatically after sequence data is provided">
{t('Run automatically')}
</span>
</Toggle>
</FormGroup>
</Form>
</FlexLeft>
<FlexRight>
{LoadExampleLink}
<ButtonRunStyled
disabled={isRunButtonDisabled}
color={runButtonColor}
onClick={run}
title={runButtonTooltip}
>
{t('Run')}
</ButtonRunStyled>
</FlexRight>
</Col>
</Row>
</SequenceFilePickerContainer>
)
}
Example #24
Source File: SystemSettings.tsx From nextclade with MIT License | 4 votes |
export function SystemSettings() {
const { t } = useTranslationSafe()
const [numThreads, setNumThreads] = useRecoilState(numThreadsAtom)
const resetNumThreads = useResetRecoilState(numThreadsAtom)
const guess = useGuessNumThreads(numThreads)
const handleValidate = useCallback((values: SettingsFormValues): FormikErrors<SettingsFormValues> => {
const errors: FormikErrors<SettingsFormValues> = {}
const { numThreads } = values
if (!Number.isInteger(numThreads) || numThreads < 0 || numThreads > 1000) {
errors.numThreads = 'Should be a positive integer from 1 to 1000'
}
return errors
}, [])
const setNumThreadsDebounced = useMemo(
() => debounce(setNumThreads, 500, { leading: false, trailing: true }), // prettier-ignore
[setNumThreads],
)
const handleSubmit = useCallback(
(values: SettingsFormValues, { setSubmitting }: FormikHelpers<SettingsFormValues>) => {
setNumThreadsDebounced(values.numThreads)
setSubmitting(false)
},
[setNumThreadsDebounced],
)
const initialValues = useMemo(() => ({ numThreads }), [numThreads])
const onReset = useCallback(() => ({ numThreads }), [numThreads])
const memoryAvailable = useMemo(() => {
return guess.memoryAvailable ? prettyBytes.format(guess.memoryAvailable) : t('unsupported')
}, [guess.memoryAvailable, t])
const memoryAvailablePerThread = useMemo(() => {
return guess.memoryAvailable ? prettyBytes.format(guess.memoryAvailable / numThreads) : t('unsupported')
}, [guess.memoryAvailable, numThreads, t])
return (
<Formik initialValues={initialValues} validate={handleValidate} onSubmit={handleSubmit} onReset={onReset}>
{({ values, errors, touched, handleChange, handleBlur, resetForm }) => (
<Form>
<FormikAutoSubmit />
<FormGroup>
<Label className="d-block w-100">
<NumericInput
id="numThreads"
min={1}
max={1000}
className={classNames('d-inline', errors?.numThreads && 'border-danger')}
type="number"
identifier="settings-num-threads-input"
value={values.numThreads}
onChange={handleChange}
onBlur={handleBlur}
/>
<span className="d-inline">
<span className="mx-3">{t('Number of CPU threads')}</span>
<span className="mx-auto">
<ButtonTransparent
className="my-0"
type="button"
title={t('Reset to default')}
// eslint-disable-next-line react-perf/jsx-no-new-function-as-prop
onClick={() => {
resetNumThreads()
resetForm()
}}
>
<MdRefresh /> {t('Reset')}
</ButtonTransparent>
</span>
</span>
{touched.numThreads && errors?.numThreads && <p className="text-danger">{errors.numThreads}</p>}
{guess.numThreads && guess.memoryAvailable && (
<Alert className="mt-2 p-1" color="primary" isOpen fade={false}>
<TableSlim borderless className="small mb-1">
<tbody>
<tr>
<td>{t('Memory available*')}</td>
<td>{memoryAvailable}</td>
</tr>
<tr>
<td>{t('Memory per CPU thread')}</td>
<td>{memoryAvailablePerThread}</td>
</tr>
<tr>
<td>{t('Recommended number of CPU threads**')}</td>
<td>{guess.numThreads ?? t('unsupported')}</td>
</tr>
<tr>
<td colSpan={2} className="small">
{t('* Current value. This amount can change depending on load')}
</td>
</tr>
<tr>
<td colSpan={2} className="small">
{t('** {{appName}} requires at least {{memoryRequired}} of memory per thread', {
appName: PROJECT_NAME,
memoryRequired: prettyBytes.format(MEMORY_BYTES_PER_THREAD_MINIMUM),
})}
</td>
</tr>
</tbody>
</TableSlim>
</Alert>
)}
</Label>
</FormGroup>
</Form>
)}
</Formik>
)
}
Example #25
Source File: FilePickerAdvanced.tsx From nextclade with MIT License | 4 votes |
export function FilePickerAdvanced() {
const { t } = useTranslation()
const [refSeq, setRefSeq] = useRecoilState(refSeqInputAtom)
const refSeqError = useRecoilValue(refSeqErrorAtom)
const resetRefSeq = useResetRecoilState(refSeqInputAtom)
const [geneMap, setGeneMap] = useRecoilState(geneMapInputAtom)
const geneMapError = useRecoilValue(geneMapErrorAtom)
const resetGeneMap = useResetRecoilState(geneMapInputAtom)
const [refTree, setRefTree] = useRecoilState(refTreeInputAtom)
const refTreeError = useRecoilValue(refTreeErrorAtom)
const resetRefTree = useResetRecoilState(refTreeInputAtom)
const [qcConfig, setQcConfig] = useRecoilState(qcConfigInputAtom)
const qcConfigError = useRecoilValue(qcConfigErrorAtom)
const resetQcConfig = useResetRecoilState(qcConfigInputAtom)
const [virusProperties, setVirusProperties] = useRecoilState(virusPropertiesInputAtom)
const virusPropertiesError = useRecoilValue(virusPropertiesErrorAtom)
const resetVirusProperties = useResetRecoilState(virusPropertiesInputAtom)
const [primersCsv, setPrimersCsv] = useRecoilState(primersCsvInputAtom)
const primersCsvError = useRecoilValue(primersCsvErrorAtom)
const resetPrimersCsv = useResetRecoilState(primersCsvInputAtom)
const iconCsv = useMemo(() => <FileIconCsv size={30} />, [])
const iconFasta = useMemo(() => <FileIconFasta size={30} />, [])
const iconGff = useMemo(() => <FileIconGff size={30} />, [])
const iconJson = useMemo(() => <FileIconJson size={30} />, [])
return (
<Row noGutters>
<Col>
<FilePicker
className="my-3"
compact
icon={iconJson}
title={t('Reference tree')}
exampleUrl="https://example.com/tree.json"
pasteInstructions={t('Enter tree data in Auspice JSON v2 format')}
input={refTree}
error={refTreeError}
onRemove={resetRefTree}
onInput={setRefTree}
/>
<FilePicker
className="my-3"
compact
icon={iconFasta}
title={t('Root sequence')}
exampleUrl="https://example.com/root_seq.fasta"
pasteInstructions={t('Enter root sequence data in FASTA or plain text format')}
input={refSeq}
error={refSeqError}
onRemove={resetRefSeq}
onInput={setRefSeq}
/>
<FilePicker
className="my-3"
compact
icon={iconJson}
title={t('Quality control')}
exampleUrl="https://example.com/qc.json"
pasteInstructions={t('Enter QC config in JSON format')}
input={qcConfig}
error={qcConfigError}
onRemove={resetQcConfig}
onInput={setQcConfig}
/>
<FilePicker
className="my-3"
compact
icon={iconJson}
title={t('Virus properties')}
exampleUrl="https://example.com/virus_properties.json"
pasteInstructions={t('Enter Virus attributes in JSON format')}
input={virusProperties}
error={virusPropertiesError}
onRemove={resetVirusProperties}
onInput={setVirusProperties}
/>
<FilePicker
className="my-3"
compact
icon={iconGff}
title={t('Gene map')}
exampleUrl="https://example.com/gene_map.json"
pasteInstructions={t('Enter gene map data in JSON format')}
input={geneMap}
error={geneMapError}
onRemove={resetGeneMap}
onInput={setGeneMap}
/>
<FilePicker
className="my-3"
compact
icon={iconCsv}
title={t('PCR primers')}
exampleUrl="https://example.com/pcr_primers.csv"
pasteInstructions={t('Enter PCR primers data in CSV format')}
input={primersCsv}
error={primersCsvError}
onRemove={resetPrimersCsv}
onInput={setPrimersCsv}
/>
</Col>
</Row>
)
}
Example #26
Source File: index.spec.tsx From recoil-persist with MIT License | 4 votes |
function testPersistWith(storage: TestableStorage) {
describe(`Storage: ${storage.name}`, () => {
const testKey = 'test-key'
const { persistAtom } = recoilPersist({ key: testKey, storage })
const getStateValue = () => {
const value = storage.getState()[testKey]
if (value == undefined) {
return {}
}
return JSON.parse(value)
}
const getAtomKey = (key: string) => {
return `${storage.name}_${key}`
}
const counterState = atom({
key: getAtomKey('count'),
default: 0,
effects_UNSTABLE: [persistAtom],
})
const counterFamily = atomFamily({
key: getAtomKey('countFamily'),
default: 0,
effects_UNSTABLE: [persistAtom],
})
const counterState4 = atom({
key: getAtomKey('count4'),
default: 0,
})
function Demo() {
const [count, setCount] = useRecoilState(counterState)
const [count2, setCount2] = useRecoilState(counterFamily('2'))
const [count3, setCount3] = useRecoilState(counterFamily('3'))
const [count4, setCount4] = useRecoilState(counterState4)
const resetCounter3 = useResetRecoilState(counterFamily('3'))
const updateMultiple = useRecoilCallback(({ set }) => () => {
set(counterState, 10)
set(counterFamily('2'), 10)
})
return (
<div>
<p data-testid="count-value">{count}</p>
<p data-testid="count2-value">{count2}</p>
<p data-testid="count3-value">{count3}</p>
<p data-testid="count4-value">{count4}</p>
<button
data-testid="count-increase"
onClick={() => setCount(count + 1)}
>
Increase
</button>
<button
data-testid="count2-increase"
onClick={() => setCount2(count2 + 1)}
>
Increase 2
</button>
<button
data-testid="count3-increase"
onClick={() => setCount3(count3 + 1)}
>
Increase 3
</button>
<button
data-testid="count4-increase"
onClick={() => setCount4(count4 + 1)}
>
Increase 4
</button>
<button
data-testid="count3-null-value"
onClick={() => setCount3(null)}
>
Set value to null
</button>
<button
data-testid="count3-undefined-value"
onClick={() => setCount3(undefined)}
>
Set value to undefined
</button>
<button data-testid="count3-reset" onClick={() => resetCounter3()}>
Reset count 3
</button>
<button
data-testid="update-multiple"
onClick={() => updateMultiple()}
>
Update multiple
</button>
</div>
)
}
beforeEach(() => {
console.error = jest.fn()
})
afterEach(() => {
storage.clear()
jest.restoreAllMocks()
})
it('should be removed from storage on reset', async () => {
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('count3-increase'))
await waitFor(() =>
expect(getByTestId('count3-value').innerHTML).toBe('1'),
)
expect(getStateValue()).toStrictEqual({
[getAtomKey('countFamily__"3"')]: 1,
})
fireEvent.click(getByTestId('count3-reset'))
await waitFor(() =>
expect(getByTestId('count3-value').innerHTML).toBe('0'),
)
expect(getStateValue()).toStrictEqual({})
})
it('should handle reset atom with default value', async () => {
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('count3-reset'))
await waitFor(() =>
expect(getByTestId('count3-value').innerHTML).toBe('0'),
)
expect(getStateValue()).toStrictEqual({})
})
it('should update storage with null', async () => {
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('count3-null-value'))
await waitFor(() =>
expect(getByTestId('count3-value').innerHTML).toBe(''),
)
expect(getStateValue()).toStrictEqual({
[getAtomKey('countFamily__"3"')]: null,
})
})
it('should update storage with undefined', async () => {
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('count3-undefined-value'))
await waitFor(() =>
expect(getByTestId('count3-value').innerHTML).toBe(''),
)
expect(getStateValue()).toStrictEqual({})
})
it('should update storage', async () => {
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('count-increase'))
await waitFor(() =>
expect(getByTestId('count-value').innerHTML).toBe('1'),
)
expect(getStateValue()).toStrictEqual({
[getAtomKey('count')]: 1,
})
})
it('should update storage if using atomFamily', async () => {
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('count2-increase'))
await waitFor(() =>
expect(getByTestId('count2-value').innerHTML).toBe('1'),
)
fireEvent.click(getByTestId('count3-increase'))
await waitFor(() =>
expect(getByTestId('count3-value').innerHTML).toBe('1'),
)
expect(getStateValue()).toStrictEqual({
[getAtomKey('countFamily__"2"')]: 1,
[getAtomKey('countFamily__"3"')]: 1,
})
})
it('should not persist atom with no effect', async () => {
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('count4-increase'))
await waitFor(() =>
expect(getByTestId('count4-value').innerHTML).toBe('1'),
)
expect(storage.getState()[testKey]).toBeUndefined()
})
it('should read state from storage', async () => {
await storage.setItem(
testKey,
JSON.stringify({
[getAtomKey('count')]: 1,
[getAtomKey('countFamily__"2"')]: 1,
}),
)
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
await waitFor(() =>
expect(getByTestId('count-value').innerHTML).toBe('1'),
)
await waitFor(() =>
expect(getByTestId('count2-value').innerHTML).toBe('1'),
)
})
it('should use default value if not in storage', async () => {
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
expect(getByTestId('count3-value').innerHTML).toBe('0')
})
it('should handle non jsonable object in storage', async () => {
storage.setItem(testKey, 'test string')
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('count-increase'))
await waitFor(() =>
expect(getByTestId('count-value').innerHTML).toBe('1'),
)
expect(getStateValue()).toStrictEqual({
[getAtomKey('count')]: 1,
})
})
it('should handle non jsonable object in state', async () => {
let mock = jest.spyOn(JSON, 'stringify').mockImplementation(() => {
throw Error('mock error')
})
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('count-increase'))
await waitFor(() =>
expect(getByTestId('count-value').innerHTML).toBe('1'),
)
expect(mock).toHaveBeenCalledTimes(1)
expect(console.error).toHaveBeenCalledTimes(1)
})
it('should handle non-existent atom name stored in storage', async () => {
storage.setItem(
testKey,
JSON.stringify({
notExist: 'test value',
}),
)
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
await waitFor(() =>
expect(getByTestId('count-value').innerHTML).toBe('0'),
)
})
it.skip('should handle updating multiple atomes', async () => {
const { getByTestId } = render(
<RecoilRoot>
<Demo />
</RecoilRoot>,
)
fireEvent.click(getByTestId('update-multiple'))
await waitFor(() =>
expect(getByTestId('count-value').innerHTML).toBe('10'),
)
await waitFor(() =>
expect(getByTestId('count2-value').innerHTML).toBe('10'),
)
expect(getStateValue()).toStrictEqual({
[getAtomKey('count')]: 10,
[getAtomKey('countFamily__"2"')]: 10,
})
})
})
}
Example #27
Source File: TransactionActions.tsx From abrechnung with GNU Affero General Public License v3.0 | 4 votes |
export default function TransactionActions({ groupID, transaction }) {
const [confirmDeleteDialogOpen, setConfirmDeleteDialogOpen] = useState(false);
const history = useHistory();
const userPermissions = useRecoilValue(currUserPermissions(groupID));
const setTransactions = useSetRecoilState(groupTransactions(transaction.group_id));
const localTransactionChanges = useRecoilValue(pendingTransactionDetailChanges(transaction.id));
const localPositionChanges = useRecoilValue(pendingTransactionPositionChanges(transaction.id));
const resetLocalTransactionChanges = useResetRecoilState(pendingTransactionDetailChanges(transaction.id));
const resetLocalPositionChanges = useResetRecoilState(pendingTransactionPositionChanges(transaction.id));
const updateTransactionAndClearLocal = useRecoilTransaction_UNSTABLE(
({ get, set, reset }) =>
(transaction: TransactionBackend) => {
set(groupTransactions(transaction.group_id), (currTransactions) => {
return currTransactions.map((t) => (t.id === transaction.id ? transaction : t));
});
reset(pendingTransactionDetailChanges(transaction.id));
reset(pendingTransactionPositionChanges(transaction.id));
}
);
const edit = () => {
if (!transaction.is_wip) {
createTransactionChange({
transactionID: transaction.id,
})
.then((t) => {
updateTransactionAndClearLocal(t);
})
.catch((err) => {
toast.error(err);
});
}
};
const abortEdit = () => {
if (transaction.is_wip) {
if (transaction.has_committed_changes) {
discardTransactionChange({
transactionID: transaction.id,
})
.then((t) => {
updateTransactionAndClearLocal(t);
})
.catch((err) => {
toast.error(err);
});
} else {
history.push(`/groups/${groupID}/`);
}
}
};
const commitEdit = () => {
if (transaction.is_wip) {
// update the transaction given the currently pending changes
// find out which local changes we have and send them to da server
const positions = Object.values(localPositionChanges.modified)
.concat(
Object.values(localPositionChanges.added).map((position) => ({
...position,
id: -1,
}))
)
.map((p) => ({
id: p.id,
name: p.name,
communist_shares: p.communist_shares,
price: p.price,
usages: p.usages,
deleted: p.deleted,
}));
if (Object.keys(localTransactionChanges).length > 0) {
updateTransaction({
transactionID: transaction.id,
description: transaction.description,
value: transaction.value,
billedAt: transaction.billed_at,
currencySymbol: transaction.currency_symbol,
currencyConversionRate: transaction.currency_conversion_rate,
creditorShares: transaction.creditor_shares,
debitorShares: transaction.debitor_shares,
...localTransactionChanges,
positions: positions.length > 0 ? positions : null,
})
.then((t) => {
updateTransactionAndClearLocal(t);
})
.catch((err) => {
toast.error(err);
});
} else if (positions.length > 0) {
updateTransactionPositions({
transactionID: transaction.id,
positions: positions,
})
.then((t) => {
updateTransactionAndClearLocal(t);
})
.catch((err) => {
toast.error(err);
});
} else {
commitTransaction({ transactionID: transaction.id })
.then((t) => {
updateTransactionAndClearLocal(t);
})
.catch((err) => {
toast.error(err);
});
}
}
};
const confirmDeleteTransaction = () => {
deleteTransaction({ transactionID: transaction.id })
.then((t) => {
// TODO: use recoil transaction
updateTransactionInState(t, setTransactions);
resetLocalPositionChanges();
resetLocalTransactionChanges();
history.push(`/groups/${groupID}/`);
})
.catch((err) => {
toast.error(err);
});
};
return (
<>
<Grid container justifyContent="space-between">
<Grid item sx={{ display: "flex", alignItems: "center" }}>
<IconButton
sx={{ display: { xs: "none", md: "inline-flex" } }}
component={RouterLink}
to={`/groups/${groupID}/`}
>
<ChevronLeft />
</IconButton>
<Chip color="primary" label={transaction.type} />
</Grid>
<Grid item>
{userPermissions.can_write && (
<>
{transaction.is_wip ? (
<>
<Button color="primary" onClick={commitEdit}>
Save
</Button>
<Button color="error" onClick={abortEdit}>
Cancel
</Button>
</>
) : (
<IconButton color="primary" onClick={edit}>
<Edit />
</IconButton>
)}
<IconButton color="error" onClick={() => setConfirmDeleteDialogOpen(true)}>
<Delete />
</IconButton>
</>
)}
</Grid>
</Grid>
<Dialog maxWidth="xs" aria-labelledby="confirmation-dialog-title" open={confirmDeleteDialogOpen}>
<DialogTitle id="confirmation-dialog-title">Confirm delete transaction</DialogTitle>
<DialogContent dividers>
Are you sure you want to delete the transaction "{transaction.description}"
</DialogContent>
<DialogActions>
<Button autoFocus onClick={() => setConfirmDeleteDialogOpen(false)} color="primary">
Cancel
</Button>
<Button onClick={confirmDeleteTransaction} color="error">
Ok
</Button>
</DialogActions>
</Dialog>
</>
);
}
Example #28
Source File: groupWatch.ts From frames with Mozilla Public License 2.0 | 4 votes |
export function useGroupWatch() {
const {user} = useUser();
const setSide = useSetRecoilState(GroupWatchSide);
const setState = useSetRecoilState(NavSectionAndOpacity);
const [med, setId] = useRecoilState(GroupWatchMediaIdAtom);
const [leader, setLeader] = useRecoilState(GroupLeader);
const [room, setRoom] = useRecoilState(GroupRoom);
const player = useRecoilValue(framesPlayer);
const addMessage = useSetRecoilState(GroupWatchMessages);
const resetMessages = useResetRecoilState(GroupWatchMessages);
const connected = useRecoilValue(ConnectedAtom);
const dispatch = useInfoDispatch();
const router = useRouter();
const base = useBase();
const socket = useChannel(room, {username: user?.username || ''});
const addNewMessage = useCallback((message: string) => {
if (user){
const nMsg = {
id: Date.now(),
username: user.username,
message: message,
received: new Date()
}
addMessage((prev) => [...prev, nMsg])
}
}, [addMessage, user])
const connect = useCallback((room: string) => {
if (user?.role === Role.GUEST) dispatch({
type: "error",
heading: "Unauthorised action attempt",
message: 'Guest accounts cannot create or join GroupWatch'
})
else if (!connected) {
setRoom(room);
socket.forceConnect(room, {username: user?.username || ''});
}
}, [user, connected, setRoom, socket, dispatch])
const sendMessage = useCallback((message: Message) => {
if (!leader) {
if (message.action === 'inform')
return;
else if (message.action === 'playing')
message.playData = undefined;
}
socket.send<GroupWatchMessage>('speak', {...message, username: user?.username || ''});
let messageString = '';
switch (message.action) {
case 'says':
messageString = message.data as string;
break;
case 'playing':
const playBool = message.data as boolean;
messageString = `You have ${playBool ? 'played' : 'paused'} the video`;
break;
case 'buffering':
const buffBool = message.data as boolean;
messageString = `You have ${buffBool ? 'lost connection' : 'reconnected'} to the video session`;
break;
case 'skipped':
messageString = `You skipped the video to the frame ${Math.ceil(message.data as number)}`;
break;
}
if (messageString !== '')
addNewMessage(messageString);
}, [socket.send, leader, user, room, addNewMessage]);
const joinRoom = useCallback(async (room: string) => {
if (user?.role === Role.GUEST) dispatch({
type: "error",
heading: "Unauthorised action attempt",
message: 'Guest accounts cannot create or join GroupWatch Sessions'
})
else {
connect(room);
}
}, [user, dispatch, setRoom, connect]);
const updateRoom = useCallback(async (auth: string) => {
if (leader && connected && base) await base.makeRequest('/api/stream/groupWatch', {
auth,
roomKey: room
}, 'POST');
}, [leader, connected, room, base]);
const pushNext = useCallback((data: string) => {
if (leader) sendMessage({action: "next", data});
}, [leader, sendMessage]);
const disconnect = useCallback(() => {
setRoom('');
resetMessages();
connected && dispatch({
type: "warn", heading: "GroupWatch Session", message: 'You have left the GroupWatch Session'
});
setLeader(false);
socket.disconnect();
}, [sendMessage, socket.disconnect, dispatch]);
const genRoom = useCallback(async (auth: string) => {
if (user?.role === Role.GUEST) dispatch({
type: "error",
heading: "Unauthorised action attempt",
message: 'Guest accounts cannot create or join GroupWatch'
})
else if (base) {
if (!socket.connected) {
const roomKey = base.generateKey(13, 5);
await base.makeRequest('/api/stream/groupWatch', {auth, roomKey}, 'POST');
connect(roomKey);
}
}
}, [user, base, dispatch, connect, socket.connected, disconnect]);
const openSession = useCallback(async (data: { id: number, auth?: string, location?: string }) => {
if (socket.connected) {
socket.disconnect();
data.location && await router.replace(`/watch=${data.location}`, undefined, {shallow: true});
} else {
if (user?.role === Role.GUEST) {
dispatch({
type: "error",
heading: "Unauthorised action attempt",
message: 'Guest accounts cannot create or join GroupWatch'
})
return;
}
player && player.pause();
setId(data);
}
}, [setId, socket.connected, socket.disconnect, user, player]);
const startSession = useCallback(async (playPause: (a : boolean) => void) => {
NProgress.start();
const url = `/room=${room}`;
const asPath = `/watch=${med?.location}`;
if (router.asPath !== url && router.asPath !== asPath)
await router.push(url);
else {
if (router.asPath.includes('watch=')) {
await router.replace(url, undefined, {shallow: true});
await playPause(true);
} else {
if (leader)
await playPause(true);
else
sendMessage({action: 'request-sync'});
}
setId(null);
setSide(false);
setState({section: 'watch', opacity: 1});
}
NProgress.done();
}, [router, room, med, setId, setSide, setState, leader, sendMessage]);
const endSession = useCallback(async (playPause: (a : boolean) => void, response?: FrameMediaLite) => {
if (response && router.asPath.includes('room')) {
const url = '/info?mediaId=' + response.id;
const asPath = `/${response.type.toLowerCase()}=${response.name.replace(/\s/g, '+')}`;
await router.push(url, asPath);
} else {
if (router.asPath.includes('watch=')) {
setState({section: 'watch', opacity: -1});
await playPause(true);
} else
setState({section: response?.type === MediaType.MOVIE ? 'movies' : 'tv shows', opacity: 1});
disconnect();
setId(null);
setSide(false);
}
}, [router, setId, setSide, setState, disconnect]);
return {
room,
channel: socket,
disconnect,
sendMessage,
pushNext,
genRoom,
updateRoom,
setLeader,
leader, startSession, endSession,
joinRoom, openSession,
connected: socket.connected,
lobbyOpen: !!med
};
}
Example #29
Source File: notificationConext.ts From frames with Mozilla Public License 2.0 | 4 votes |
NotificationHandler = () => {
const router = useRouter();
const infoDispatch = useInfoDispatch();
const confirmDispatch = useConfirmDispatch();
const videoState = useRecoilValue(framesVideoStateAtom);
const resetPlayer = useResetRecoilState(framesPlayer);
const setIsStreaming = useSetRecoilState(AlreadyStreamingAtom);
const startTime = useRecoilValue(fullscreenAddressAtom).startTime;
const {user, globalTopic, notificationChannel, globalChannel, connect, disconnect, broadcastToSelf, signOut} = useNotification();
useEffect(() => {
if (user && globalTopic)
connect();
else
disconnect();
}, [user, globalTopic]);
notificationChannel.subscribe<NotificationInterface>('shout', async data => {
switch (data.type) {
case 'streaming':
const stream = /\/(frame|watch|room)=\w/.test(router.asPath) ;
if (videoState && stream) {
const nData = {
name: videoState.name,
backdrop: videoState.backdrop,
episodeName: videoState.episodeName,
logo: videoState.logo,
startTime: startTime,
};
broadcastToSelf({
type: 'isStreaming',
title: 'Streaming',
message: `${startTime}`,
recipient: data.sender,
data: nData,
});
}
break;
case 'isStreaming':
if (data.data && data.data.startTime < startTime && data.recipient === user?.session)
setIsStreaming(data.data);
break;
case 'doneStreaming':
resetPlayer();
setIsStreaming(null);
break;
case 'signOut':
infoDispatch({
type: 'error',
heading: data.title,
message: data.message,
})
await signOut();
break;
default:
break;
}
})
globalChannel.subscribe<NotificationInterface & {type: string}>('shout', data => {
})
globalChannel.subscribe<{body: NotificationInterface & {type: string}}>('whisper', async ({body: data}) => {
switch (data.type) {
case 'groupWatchInvite':
confirmDispatch({
type: 'user',
heading: data.title,
message: data.message,
confirm: true,
confirmText: 'Join',
cancelText: 'Decline',
onOk: async () => {
await router.push(data.data.url);
},
onCancel: () => {},
})
break;
default:
break;
}
})
return null;
}