Skip to content
This repository has been archived by the owner on Sep 13, 2021. It is now read-only.

Commit

Permalink
Merge pull request #441 from skoleapp/general-fixes
Browse files Browse the repository at this point in the history
Misc v2.0 fixes
  • Loading branch information
blomqma authored Apr 13, 2021
2 parents 77ca90e + 4b273ff commit 8ce9256
Show file tree
Hide file tree
Showing 22 changed files with 202 additions and 150 deletions.
2 changes: 1 addition & 1 deletion src/components/activity/ActivityListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const ActivityListItem: React.FC<Props> = ({
const context = useLanguageHeaderContext();
const { t } = useTranslation();
const { profileUrl } = useAuthContext();
const avatarThumbnail = R.prop('avatarThumbnail', causingUser);
const avatarThumbnail = R.propOr('', 'avatarThumbnail', causingUser);

const onCompleted = ({ markActivityAsRead }: MarkActivityAsReadMutation): void => {
if (markActivityAsRead?.errors?.length) {
Expand Down
34 changes: 16 additions & 18 deletions src/components/dialogs/CustomInviteDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import ArrowForwardOutlined from '@material-ui/icons/ArrowForwardOutlined';
import FileCopyOutlined from '@material-ui/icons/FileCopyOutlined';
import { useAuthContext, useNotificationsContext, useShareContext } from 'context';
import { useTranslation } from 'lib';
import { useRouter } from 'next/router';
import React, { useCallback, useMemo } from 'react';
import { useMediaQueries } from 'styles';
import { ShareDialogParams } from 'types';
import { SLOGAN } from 'utils';

import { DialogHeader } from './DialogHeader';
Expand All @@ -34,36 +32,37 @@ interface Props {
header?: JSX.Element | string;
dynamicContent: JSX.Element[];
handleClose: () => void;
shareDialogParams?: ShareDialogParams;
hideInviteCode?: boolean;
handleClickInviteButton?: () => void;
}

export const CustomInviteDialog: React.FC<Props> = ({
open,
header,
dynamicContent,
handleClose,
shareDialogParams: _shareDialogParams,
hideInviteCode,
handleClickInviteButton: _handleClickInviteButton,
}) => {
const classes = useStyles();
const { t } = useTranslation();
const { inviteCode } = useAuthContext();
const { asPath } = useRouter();
const { mdUp } = useMediaQueries();
const { handleOpenShareDialog } = useShareContext();
const { toggleNotification } = useNotificationsContext();
const { username } = useAuthContext();
const title = t('common:inviteTitle', { username });
const text = SLOGAN;
const customLink = `${process.env.FRONTEND_URL}?code=${inviteCode}`;

const shareDialogParams = useMemo(
() =>
_shareDialogParams || {
header: t('common:inviteShareDialogHeader'),
title: t('common:inviteTitle', { username }),
text: SLOGAN,
linkSuffix: `?code=${inviteCode}`,
},
[t, inviteCode, _shareDialogParams, username],
() => ({
header: t('common:inviteShareDialogHeader'),
title,
text,
customLink,
}),
[t, text, title, customLink],
);

const handleClickInviteButton = useCallback(async (): Promise<void> => {
Expand All @@ -72,21 +71,20 @@ export const CustomInviteDialog: React.FC<Props> = ({
handleOpenShareDialog(shareDialogParams);
} else {
const { navigator } = window;
const { title, text, linkSuffix } = shareDialogParams;

if (navigator?.share) {
try {
await navigator.share({
title,
text,
url: `${process.env.FRONTEND_URL}${asPath}${linkSuffix}`,
url: customLink,
});
} catch {
// User cancelled.
}
}
}
}, [asPath, handleOpenShareDialog, mdUp, handleClose, shareDialogParams]);
}, [handleOpenShareDialog, mdUp, handleClose, shareDialogParams, customLink, text, title]);

const handleClickCopyCodeButton = useCallback((): void => {
toggleNotification(t('common:inviteCodeCopied'));
Expand Down Expand Up @@ -128,14 +126,14 @@ export const CustomInviteDialog: React.FC<Props> = ({
() => (
<Button
variant="contained"
onClick={handleClickInviteButton}
onClick={_handleClickInviteButton || handleClickInviteButton}
endIcon={<ArrowForwardOutlined />}
fullWidth
>
{t('common:inviteButtonText')}
</Button>
),
[handleClickInviteButton, t],
[handleClickInviteButton, t, _handleClickInviteButton],
);

return (
Expand Down
4 changes: 2 additions & 2 deletions src/components/dialogs/SkoleDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const SkoleDialog: React.FC<SkoleDialogProps> = ({
...props
}) => {
const classes = useStyles();
const { smDown, smUp } = useMediaQueries();
const { smDown, mdUp } = useMediaQueries();

const PaperProps = {
className: clsx(
Expand All @@ -50,7 +50,7 @@ export const SkoleDialog: React.FC<SkoleDialogProps> = ({
<Dialog
onClick={(e): void => e.stopPropagation()}
fullScreen={fullScreen === false ? fullScreen : smDown}
fullWidth={smUp}
fullWidth={mdUp}
TransitionComponent={Transition}
PaperProps={PaperProps}
{...props}
Expand Down
153 changes: 104 additions & 49 deletions src/components/layout/TopNavbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import HowToRegOutlined from '@material-ui/icons/HowToRegOutlined';
import LaunchOutlined from '@material-ui/icons/LaunchOutlined';
import NotificationsOutlined from '@material-ui/icons/NotificationsOutlined';
import StarBorderOutlined from '@material-ui/icons/StarBorderOutlined';
import clsx from 'clsx';
import { useAuthContext, useDarkModeContext, useInviteContext } from 'context';
import { useTranslation } from 'lib';
import React, { MouseEvent, useCallback, useMemo, useState } from 'react';
Expand Down Expand Up @@ -63,6 +64,9 @@ const useStyles = makeStyles(({ breakpoints, spacing }) => ({
paddingRight: spacing(4),
},
},
buttonSpacing: {
marginLeft: spacing(1),
},
activityPopper: {
zIndex: 3, // Overlap top navbar.
},
Expand All @@ -84,6 +88,7 @@ export const TopNavbar: React.FC<TopNavbarProps> = ({
hideBackButton,
hideSearch,
hideDynamicButtons,
hideDynamicAuthButtons,
hideLoginButton,
hideRegisterButton,
hideGetStartedButton,
Expand All @@ -102,6 +107,7 @@ export const TopNavbar: React.FC<TopNavbarProps> = ({
const dense = !!renderHeaderLeft || !!renderHeaderRightSecondary;
const [activityPopperOpen, setActivityPopperOpen] = useState(false);
const { handleOpenGeneralInviteDialog } = useInviteContext();
const { verified } = useAuthContext();

const {
userMe,
Expand Down Expand Up @@ -144,20 +150,21 @@ export const TopNavbar: React.FC<TopNavbarProps> = ({

const renderLogo = useMemo(() => !hideLogo && <Logo />, [hideLogo]);

const renderLanguageButton = useMemo(() => !hideLanguageButton && <LanguageButton />, [
hideLanguageButton,
]);
const renderLanguageButton = useMemo(
() => !hideLanguageButton && <LanguageButton className={classes.buttonSpacing} />,
[hideLanguageButton, classes.buttonSpacing],
);

const renderDarkModeButton = useMemo(
() =>
!hideDarkModeButton && (
<Tooltip title={t('common-tooltips:toggleDarkMode')}>
<IconButton onClick={toggleDarkMode} color="secondary">
<IconButton className={classes.buttonSpacing} onClick={toggleDarkMode} color="secondary">
{darkMode ? <Brightness7Outlined /> : <Brightness6Outlined />}
</IconButton>
</Tooltip>
),
[darkMode, hideDarkModeButton, t, toggleDarkMode],
[darkMode, hideDarkModeButton, t, toggleDarkMode, classes.buttonSpacing],
);

const renderMobileContent = useMemo(
Expand Down Expand Up @@ -192,14 +199,18 @@ export const TopNavbar: React.FC<TopNavbarProps> = ({
const renderActivityButton = useMemo(
() => (
<Tooltip title={t('common-tooltips:activity', { unreadActivityCount })}>
<IconButton onClick={handleActivityButtonClick} color="secondary">
<IconButton
className={classes.buttonSpacing}
onClick={handleActivityButtonClick}
color="secondary"
>
<Badge badgeContent={unreadActivityCount} color="secondary">
<NotificationsOutlined />
</Badge>
</IconButton>
</Tooltip>
),
[handleActivityButtonClick, t, unreadActivityCount],
[handleActivityButtonClick, t, unreadActivityCount, classes.buttonSpacing],
);

const renderActivityPopper = useMemo(
Expand Down Expand Up @@ -267,57 +278,101 @@ export const TopNavbar: React.FC<TopNavbarProps> = ({
[rank, renderRankEmoji, renderScore],
);

const renderInviteButton = useMemo(
() =>
!!verified && (
<Tooltip title={t('common-tooltips:invite', { inviteCodeUsages })}>
<IconButton
className={classes.buttonSpacing}
onClick={handleOpenGeneralInviteDialog}
color="secondary"
>
<Badge badgeContent={inviteCodeUsages} color="secondary">
<ContactMailOutlined />
</Badge>
</IconButton>
</Tooltip>
),
[handleOpenGeneralInviteDialog, inviteCodeUsages, t, verified, classes.buttonSpacing],
);

const renderActivity = useMemo(
() =>
!!verified && (
<ClickAwayListener onClickAway={handleActivityPopperClickAway}>
<Box // ClickAway listener requires exactly one child element that cannot be a fragment.
>
{renderActivityButton}
{renderActivityPopper}
</Box>
</ClickAwayListener>
),
[renderActivityButton, renderActivityPopper, verified],
);

const renderStarButton = useMemo(
() =>
!!verified && (
<Tooltip title={t('common-tooltips:starred')}>
<IconButtonLink
icon={StarBorderOutlined}
href={urls.starred}
className={classes.buttonSpacing}
color="secondary"
/>
</Tooltip>
),
[verified, t, classes.buttonSpacing],
);

const renderRank = useMemo(
() => (
<Link href={urls.score}>
<Tooltip title={t('common-tooltips:ownRank', { rank, score })}>
<Chip className={clsx(classes.buttonSpacing, 'rank-chip')} label={renderRankLabel} />
</Tooltip>
</Link>
),
[t, rank, renderRankLabel, score, classes.buttonSpacing],
);

const renderAvatar = useMemo(
() => (
<Tooltip title={t('common-tooltips:profile')}>
<Typography component="span">
<Link href={profileUrl}>
<IconButton className={classes.buttonSpacing} color="secondary">
<Avatar className="avatar-thumbnail" src={avatarThumbnail} />
</IconButton>
</Link>
</Typography>
</Tooltip>
),
[avatarThumbnail, profileUrl, t, classes.buttonSpacing],
);

const renderAuthenticatedButtons = useMemo(
() =>
!!userMe &&
!hideDynamicButtons && (
!hideDynamicButtons &&
!hideDynamicAuthButtons && (
<>
<Tooltip title={t('common-tooltips:invite', { inviteCodeUsages })}>
<IconButton onClick={handleOpenGeneralInviteDialog} color="secondary">
<Badge badgeContent={inviteCodeUsages} color="secondary">
<ContactMailOutlined />
</Badge>
</IconButton>
</Tooltip>
<ClickAwayListener onClickAway={handleActivityPopperClickAway}>
<Box // ClickAway listener requires exactly one child element that cannot be a fragment.
>
{renderActivityButton}
{renderActivityPopper}
</Box>
</ClickAwayListener>
<Tooltip title={t('common-tooltips:starred')}>
<IconButtonLink icon={StarBorderOutlined} href={urls.starred} color="secondary" />
</Tooltip>
<Link href={urls.score}>
<Tooltip title={t('common-tooltips:ownRank', { rank, score })}>
<Chip className="rank-chip" label={renderRankLabel} />
</Tooltip>
</Link>
<Tooltip title={t('common-tooltips:profile')}>
<Typography component="span">
<Link href={profileUrl}>
<IconButton color="secondary">
<Avatar className="avatar-thumbnail" src={avatarThumbnail} />
</IconButton>
</Link>
</Typography>
</Tooltip>
{renderInviteButton}
{renderActivity}
{renderStarButton}
{renderRank}
{renderAvatar}
</>
),
[
avatarThumbnail,
hideDynamicAuthButtons,
hideDynamicButtons,
profileUrl,
rank,
renderActivityButton,
renderActivityPopper,
renderRankLabel,
score,
t,
renderActivity,
renderAvatar,
renderInviteButton,
renderRank,
renderStarButton,
userMe,
inviteCodeUsages,
handleOpenGeneralInviteDialog,
],
);

Expand Down
6 changes: 3 additions & 3 deletions src/components/shared/LanguageButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import IconButton from '@material-ui/core/IconButton';
import IconButton, { IconButtonProps } from '@material-ui/core/IconButton';
import Tooltip from '@material-ui/core/Tooltip';
import { useLanguageContext } from 'context';
import { useTranslation } from 'lib';
Expand All @@ -7,15 +7,15 @@ import { useMediaQueries } from 'styles';

import { LanguageFlag } from './LanguageFlag';

export const LanguageButton: React.FC = () => {
export const LanguageButton: React.FC<IconButtonProps> = (props) => {
const { t, lang } = useTranslation();
const { handleOpenLanguageMenu } = useLanguageContext();
const { smDown } = useMediaQueries();
const size = smDown ? 'small' : 'medium';

return (
<Tooltip title={t('common-tooltips:language')}>
<IconButton onClick={handleOpenLanguageMenu} size={size}>
<IconButton onClick={handleOpenLanguageMenu} size={size} {...props}>
<LanguageFlag lang={lang} />
</IconButton>
</Tooltip>
Expand Down
1 change: 0 additions & 1 deletion src/components/shared/TopNavbarSearchWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const useStyles = makeStyles(({ palette, spacing }) => ({
borderRadius: BORDER_RADIUS,
color: palette.common.white,
padding: `${spacing(1)} ${spacing(3)}`,
marginRight: spacing(2),
'&:hover': {
backgroundColor: 'rgba(255, 255, 255, 0.25)',
},
Expand Down
Loading

0 comments on commit 8ce9256

Please sign in to comment.