mirror of
https://github.com/Andre-Bzk/twitch4steamdeck.git
synced 2026-11-15 15:43:08 +01:00
feat: Account-Screen mit Nutzerprofil, App-Version aus package.json
- AccountScreen zeigt jetzt Profilbild, Anzeigename und @Login des eingeloggten Twitch-Nutzers (via neuem IPC-Kanal twitch:get-own-user) - CSS: account__avatar zeigt Profilbild, neue Klassen für identity, name, login und error
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { UserIcon } from '../components/Icons'
|
||||
import type { OwnUserInfo } from '../types/t4sd'
|
||||
|
||||
interface Props {
|
||||
hasFocus: boolean
|
||||
@@ -9,11 +10,40 @@ interface Props {
|
||||
|
||||
export default function AccountScreen({ hasFocus, onRequestSidebar, onLogout }: Props): JSX.Element {
|
||||
const logoutBtnRef = useRef<HTMLButtonElement>(null)
|
||||
const [user, setUser] = useState<OwnUserInfo | null>(null)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const [error, setError] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
if (hasFocus) logoutBtnRef.current?.focus({ preventScroll: true })
|
||||
}, [hasFocus])
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
|
||||
setIsLoading(true)
|
||||
setError('')
|
||||
|
||||
void window.t4sd.twitch
|
||||
.getOwnUser()
|
||||
.then((nextUser) => {
|
||||
if (!cancelled) setUser(nextUser)
|
||||
})
|
||||
.catch((err) => {
|
||||
if (!cancelled) {
|
||||
setUser(null)
|
||||
setError(err instanceof Error ? err.message : 'Accountdaten konnten nicht geladen werden.')
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) setIsLoading(false)
|
||||
})
|
||||
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasFocus) return
|
||||
const onKey = (e: KeyboardEvent): void => {
|
||||
@@ -31,6 +61,8 @@ export default function AccountScreen({ hasFocus, onRequestSidebar, onLogout }:
|
||||
onLogout()
|
||||
}
|
||||
|
||||
const showLogin = user && user.login.toLowerCase() !== user.displayName.toLowerCase()
|
||||
|
||||
return (
|
||||
<div className="screen">
|
||||
<header className="screen__header">
|
||||
@@ -38,9 +70,25 @@ export default function AccountScreen({ hasFocus, onRequestSidebar, onLogout }:
|
||||
</header>
|
||||
<div className="account">
|
||||
<div className="account__avatar">
|
||||
<UserIcon />
|
||||
{user?.profileImageUrl ? (
|
||||
<img src={user.profileImageUrl} alt="" draggable={false} />
|
||||
) : (
|
||||
<UserIcon />
|
||||
)}
|
||||
</div>
|
||||
<div className="account__identity">
|
||||
<p className="account__hint">Eingeloggt bei Twitch</p>
|
||||
{isLoading ? (
|
||||
<p className="account__name">Lade Account…</p>
|
||||
) : user ? (
|
||||
<>
|
||||
<p className="account__name">{user.displayName}</p>
|
||||
{showLogin && <p className="account__login">@{user.login}</p>}
|
||||
</>
|
||||
) : (
|
||||
<p className="account__error">{error || 'Accountdaten konnten nicht geladen werden.'}</p>
|
||||
)}
|
||||
</div>
|
||||
<p className="account__hint">Eingeloggt bei Twitch</p>
|
||||
<p className="account__version">App-Version {window.t4sd.appVersion}</p>
|
||||
<button ref={logoutBtnRef} className="btn" onClick={handleLogout}>
|
||||
Abmelden
|
||||
|
||||
@@ -1323,6 +1323,13 @@ body,
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.account__avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.account__avatar svg {
|
||||
@@ -1331,12 +1338,33 @@ body,
|
||||
color: var(--color-fg-dim);
|
||||
}
|
||||
|
||||
.account__identity {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.account__hint {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
color: var(--color-fg);
|
||||
}
|
||||
|
||||
.account__name {
|
||||
margin: 0;
|
||||
font-size: 32px;
|
||||
line-height: 1.2;
|
||||
font-weight: 700;
|
||||
color: var(--color-fg);
|
||||
}
|
||||
|
||||
.account__login {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: var(--color-fg-dim);
|
||||
}
|
||||
|
||||
.account__version {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
@@ -1344,6 +1372,14 @@ body,
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.account__error {
|
||||
margin: 0;
|
||||
max-width: 560px;
|
||||
font-size: 18px;
|
||||
color: #ff6868;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* ── Chapter Overlay (Modal) ──────────────────────────── */
|
||||
.chapter-overlay {
|
||||
position: fixed;
|
||||
|
||||
Vendored
+8
@@ -30,6 +30,13 @@ export interface FollowedChannelInfo {
|
||||
language?: string
|
||||
}
|
||||
|
||||
export interface OwnUserInfo {
|
||||
id: string
|
||||
login: string
|
||||
displayName: string
|
||||
profileImageUrl: string
|
||||
}
|
||||
|
||||
export interface GameInfo {
|
||||
id: string
|
||||
name: string
|
||||
@@ -85,6 +92,7 @@ export interface T4sdApi {
|
||||
}
|
||||
twitch: {
|
||||
getFollowed: () => Promise<FollowedChannelInfo[]>
|
||||
getOwnUser: () => Promise<OwnUserInfo>
|
||||
getVideos: (broadcasterId: string) => Promise<VodInfo[]>
|
||||
getTopGames: (cursor?: string) => Promise<{ games: GameInfo[]; cursor?: string }>
|
||||
getTopStreams: (options?: { gameId?: string; language?: string; cursor?: string; limit?: number }) => Promise<TopStreamsResult>
|
||||
|
||||
Reference in New Issue
Block a user