fix: use non-native tooltip for recent event

This commit is contained in:
Ash Keel 2024-02-25 21:20:08 +01:00
parent b5f5c2975c
commit 3c3ea7bdb4
No known key found for this signature in database
GPG Key ID: 53A9E9A6035DD109
4 changed files with 98 additions and 16 deletions

View File

@ -8,7 +8,14 @@ import {
import { useLiveKey, useModule } from '~/lib/react';
import { useAppDispatch, useAppSelector } from '~/store';
import { modules } from '~/store/api/reducer';
import { PageContainer, SectionHeader, styled, TextBlock } from '../theme';
import * as HoverCard from '@radix-ui/react-hover-card';
import {
PageContainer,
SectionHeader,
styled,
TextBlock,
TooltipContent,
} from '../theme';
import BrowserLink from '../components/BrowserLink';
import Scrollbar from '../components/utils/Scrollbar';
import RevealLink from '../components/utils/RevealLink';
@ -345,15 +352,21 @@ function TwitchEventLog({ events }: { events: EventSubNotification[] }) {
const { t } = useTranslation();
return (
<>
<SectionHeader>
{t('pages.dashboard.twitch-events.header')}
<a
style={{ marginLeft: '10px' }}
title={t('pages.dashboard.twitch-events.warning')}
>
<InfoCircledIcon />
</a>
</SectionHeader>
<HoverCard.Root>
<HoverCard.Trigger asChild>
<SectionHeader>
{t('pages.dashboard.twitch-events.header')}
<a style={{ marginLeft: '10px' }}>
<InfoCircledIcon />
</a>
</SectionHeader>
</HoverCard.Trigger>
<HoverCard.Portal>
<TooltipContent>
{t('pages.dashboard.twitch-events.warning')}
</TooltipContent>
</HoverCard.Portal>
</HoverCard.Root>
<Scrollbar vertical={true} viewport={{ maxHeight: '250px' }}>
<EventListContainer>
{events
@ -427,10 +440,15 @@ function TwitchSection() {
);
}
function ProblemList() {
return <></>;
}
export default function Dashboard(): React.ReactElement {
const { t } = useTranslation();
return (
<PageContainer>
<ProblemList />
<TwitchSection />
<SectionHeader>{t('pages.dashboard.quick-links')}</SectionHeader>
<UsefulLinksMenu>

View File

@ -26,6 +26,8 @@ import extensionsReducer, {
startExtension,
stopExtension,
} from '~/store/extensions/reducer';
import { useModule } from '~/lib/react';
import { modules } from '~/store/api/reducer';
import AlertContent from '../components/AlertContent';
import DialogContent from '../components/DialogContent';
import Loading from '../components/Loading';
@ -37,6 +39,7 @@ import {
DialogActions,
Field,
FlexRow,
getTheme,
InputBox,
Label,
MultiButton,
@ -220,7 +223,7 @@ function ExtensionListItem(props: ExtensionListItemProps) {
}}
showCancel={false}
>
<code>{props.error.toString()}</code>
<code>{props.error.message}</code>
</AlertContent>
</Alert>
) : null}
@ -583,6 +586,7 @@ function ExtensionEditor() {
}
export default function ExtensionsPage(): React.ReactElement {
const [uiConfig] = useModule(modules.uiConfig);
const { t } = useTranslation();
const extensions = useAppSelector((state) => state.extensions);
const dispatch = useAppDispatch();
@ -619,12 +623,20 @@ export default function ExtensionsPage(): React.ReactElement {
};
if (!extensions.ready) {
const theme = getTheme(
uiConfig?.theme ?? localStorage.getItem('theme') ?? 'dark',
);
return (
<PageContainer>
<PageHeader>
<PageTitle>{t('pages.extensions.title')}</PageTitle>
</PageHeader>
<Loading size="fill" message={t('pages.extensions.loading')} />
<Loading
theme={theme}
size="fill"
message={t('pages.extensions.loading')}
/>
</PageContainer>
);
}

View File

@ -1,5 +1,6 @@
/* eslint-disable import/prefer-default-export */
import { Content as HoverCardContent } from '@radix-ui/react-hover-card';
import { styled, theme } from './theme';
export const FlexRow = styled('div', {
@ -26,3 +27,15 @@ export const FlexRow = styled('div', {
},
},
});
export const TooltipContent = styled(HoverCardContent, {
borderRadius: 6,
display: 'flex',
padding: '0.5rem',
gap: '0.5rem',
flexDirection: 'column',
border: '2px solid $gray6',
backgroundColor: '$gray2',
alignItems: 'flex-start',
boxShadow: '0px 5px 20px rgba(0,0,0,0.4)',
});

View File

@ -3,6 +3,7 @@ package twitch
import (
"fmt"
"net/http"
"slices"
"time"
"github.com/nicklaw5/helix/v2"
@ -16,22 +17,60 @@ type AuthResponse struct {
Time time.Time
}
var scopes = []string{
"bits:read",
"channel:bot",
"channel:moderate",
"channel:read:hype_train",
"channel:read:polls",
"channel:read:predictions",
"channel:read:redemptions",
"channel:read:subscriptions",
"chat:edit",
"chat:read",
"moderator:manage:announcements",
"moderator:read:chatters",
"moderator:read:followers",
"user_read",
"user:bot",
"user:manage:whispers",
"user:read:chat",
"whispers:edit",
"whispers:read",
}
func (c *Client) GetAuthorizationURL() string {
if c.API == nil {
return "twitch-not-configured"
}
return c.API.GetAuthorizationURL(&helix.AuthorizationURLParams{
ResponseType: "code",
Scopes: []string{"bits:read channel:read:subscriptions channel:read:redemptions channel:read:polls channel:read:predictions channel:read:hype_train user_read chat:read chat:edit channel:moderate whispers:read whispers:edit moderator:read:chatters moderator:read:followers user:manage:whispers moderator:manage:announcements"},
Scopes: scopes,
})
}
// CheckScopes checks if the user has authorized all required scopes
// Normally this would be the case but between versions strimertul has changed
// the required scopes, and it's possible that some users have not re-authorized
// the application with the new scopes.
func (c *Client) CheckScopes() (bool, error) {
var authResp AuthResponse
if err := c.db.GetJSON(AuthKey, &authResp); err != nil {
return false, err
}
// Sort scopes for comparison
slices.Sort(authResp.Scope)
return slices.Equal(scopes, authResp.Scope), nil
}
func (c *Client) GetUserClient(forceRefresh bool) (*helix.Client, error) {
var authResp AuthResponse
err := c.db.GetJSON(AuthKey, &authResp)
if err != nil {
if err := c.db.GetJSON(AuthKey, &authResp); err != nil {
return nil, err
}
// Handle token expiration
if forceRefresh || time.Now().After(authResp.Time.Add(time.Duration(authResp.ExpiresIn)*time.Second)) {
// Refresh tokens
@ -108,7 +147,7 @@ func (c *Client) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return
}
w.Header().Add("Content-Type", "text/html")
fmt.Fprintf(w, `<html><body><h2>All done, you can close me now!</h2><script>window.close();</script></body></html>`)
_, _ = fmt.Fprintf(w, `<html><body><h2>All done, you can close me now!</h2><script>window.close();</script></body></html>`)
}
type RefreshResponse struct {