Skip to content

Commit

Permalink
[Tech] Handle login in a single place (#1306)
Browse files Browse the repository at this point in the history
  • Loading branch information
arielj authored May 15, 2022
1 parent be995e7 commit 43c1eaa
Show file tree
Hide file tree
Showing 15 changed files with 262 additions and 189 deletions.
6 changes: 4 additions & 2 deletions electron/gog/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export class GOGUser {
data.loginTime = Date.now()
configStore.set('credentials', data)
logInfo('Login Successful', LogPrefix.Gog)
await this.getUserDetails()
return { status: 'done' }
const userDetails = await this.getUserDetails()
return { status: 'done', data: userDetails }
}

public static async getUserDetails() {
Expand Down Expand Up @@ -59,6 +59,8 @@ export class GOGUser {

configStore.set('userData', data)
logInfo('Saved user data to config', LogPrefix.Gog)

return data
}
/**
* Loads user credentials from config
Expand Down
5 changes: 3 additions & 2 deletions electron/legendary/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ export class LegendaryUser {
['Failed to login with Legendary:', res.error],
LogPrefix.Legendary
)
return
return { status: 'failed' }
}
this.getUserInfo()
const userInfo = await this.getUserInfo()
return { status: 'done', data: userInfo }
}

public static async logout() {
Expand Down
15 changes: 2 additions & 13 deletions electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,12 +626,6 @@ ipcMain.on('resetHeroic', async () => {
}
})

ipcMain.handle('authGOG', async (event, code) =>
GOGUser.login(code).then(() =>
mainWindow.webContents.send('updateLoginState')
)
)

ipcMain.on('createNewWindow', async (e, url) =>
new BrowserWindow({ height: 700, width: 1200 }).loadURL(url)
)
Expand Down Expand Up @@ -685,13 +679,8 @@ ipcMain.handle('getUserInfo', async () => LegendaryUser.getUserInfo())
// Checks if the user have logged in with Legendary already
ipcMain.handle('isLoggedIn', async () => LegendaryUser.isLoggedIn())

ipcMain.handle('login', async (event, sid) =>
LegendaryUser.login(sid).then((value) => {
mainWindow.webContents.send('updateLoginState')
return value
})
)

ipcMain.handle('login', async (event, sid) => LegendaryUser.login(sid))
ipcMain.handle('authGOG', async (event, code) => GOGUser.login(code))
ipcMain.handle('logoutLegendary', async () => LegendaryUser.logout())
ipcMain.handle('logoutGOG', async () => GOGUser.logout())

Expand Down
7 changes: 5 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@ import Accessibility from './screens/Accessibility'
import ContextProvider from './state/ContextProvider'

function App() {
const { contentFontFamily, actionsFontFamily } = useContext(ContextProvider)
const { epic, gog, contentFontFamily, actionsFontFamily } =
useContext(ContextProvider)

const style = {
'--content-font-family': contentFontFamily,
'--actions-font-family': actionsFontFamily
} as React.CSSProperties

const loggedIn = epic.username || gog.username

return (
<div className="App" style={style}>
<HashRouter>
<Sidebar />
<main className="content">
<Routes>
<Route path="/" element={<Library />} />
<Route path="/" element={loggedIn ? <Library /> : <Login />} />
<Route path="login" element={<Login />} />
<Route path="epicstore" element={<WebView />} />
<Route path="gogstore" element={<WebView />} />
Expand Down
71 changes: 38 additions & 33 deletions src/components/UI/Sidebar/components/SidebarLinks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import classNames from 'classnames'
import cx from 'classnames'
import React, { useCallback, useContext, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { NavLink, useNavigate, useLocation } from 'react-router-dom'
import { NavLink, useLocation } from 'react-router-dom'
import { getAppSettings } from 'src/helpers'
import { configStore, gogConfigStore } from 'src/helpers/electronStores'
import ContextProvider from 'src/state/ContextProvider'
import { Runner } from 'src/types'
import './index.css'
Expand All @@ -28,15 +27,14 @@ interface LocationState {

export default function SidebarLinks() {
const { t } = useTranslation()
const navigate = useNavigate()
const [showUnrealMarket, setShowUnrealMarket] = useState(false)
const { state } = useLocation() as { state: LocationState }
const location = useLocation() as { pathname: string }
const [appName, type] = location.pathname
.replaceAll('/settings/', '')
.split('/')

const { category, handleCategory, handleFilter, platform } =
const { epic, gog, category, handleCategory, handleFilter, platform } =
useContext(ContextProvider)

const isLibrary = location.pathname === '/'
Expand All @@ -55,15 +53,11 @@ export default function SidebarLinks() {

const shouldRenderWineSettings = !isWin && !isMacGame && !isLinuxGame

const isEpicLoggedIn = Boolean(configStore.get('userInfo'))
const isGOGLoggedIn = Boolean(gogConfigStore.get('credentials'))
const showLibrarySubmenu =
((isEpicLoggedIn && isGOGLoggedIn) ||
(isEpicLoggedIn && showUnrealMarket)) &&
((epic.username && gog.username) || (epic.username && showUnrealMarket)) &&
isLibrary

const pressAction = !isEpicLoggedIn && !isGOGLoggedIn ? '/login' : '/'
const displayIcon = isEpicLoggedIn || isGOGLoggedIn ? faGamepad : faUser
const loggedIn = epic.username || gog.username

const toggleCategory = useCallback(
(newCategory: string) => {
Expand All @@ -79,32 +73,43 @@ export default function SidebarLinks() {
getAppSettings().then(({ showUnrealMarket }) =>
setShowUnrealMarket(showUnrealMarket)
)
if (!isEpicLoggedIn && !isGOGLoggedIn) {
return navigate('/login')
}
}, [isEpicLoggedIn, isGOGLoggedIn, navigate])
}, [])

return (
<div className="SidebarLinks Sidebar__section">
<NavLink
data-testid="library"
className={({ isActive }) =>
classNames('Sidebar__item', { active: isActive })
}
to={pressAction}
>
<>
<div className="Sidebar__itemIcon">
<FontAwesomeIcon icon={displayIcon} />
</div>
{isEpicLoggedIn || isGOGLoggedIn
? t('Library')
: t('button.login', 'Login')}
</>
</NavLink>
{loggedIn && (
<NavLink
className={({ isActive }) =>
classNames('Sidebar__item', { active: isActive })
}
to={'/'}
>
<>
<div className="Sidebar__itemIcon">
<FontAwesomeIcon icon={faGamepad} />
</div>
{t('Library')}
</>
</NavLink>
)}
{!loggedIn && (
<NavLink
className={({ isActive }) =>
classNames('Sidebar__item', { active: isActive })
}
to={'/login'}
>
<>
<div className="Sidebar__itemIcon">
<FontAwesomeIcon icon={faUser} />
</div>
{t('button.login', 'Login')}
</>
</NavLink>
)}
{showLibrarySubmenu && (
<>
{isEpicLoggedIn && (
{epic.username && (
<a
href="#"
onClick={() => toggleCategory('epic')}
Expand All @@ -115,7 +120,7 @@ export default function SidebarLinks() {
{t('Epic Games', 'Epic Games')}
</a>
)}
{isGOGLoggedIn && (
{gog.username && (
<a
href="#"
onClick={() => toggleCategory('gog')}
Expand All @@ -126,7 +131,7 @@ export default function SidebarLinks() {
{t('GOG', 'GOG')}
</a>
)}
{showUnrealMarket && isEpicLoggedIn && (
{showUnrealMarket && epic.username && (
<a
href="#"
onClick={() => toggleCategory('unreal')}
Expand Down
7 changes: 3 additions & 4 deletions src/components/UI/Sidebar/components/SidebarUtils/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import React from 'react'
import { useTranslation } from 'react-i18next'
import { NavLink, useNavigate } from 'react-router-dom'
import { openDiscordLink } from 'src/helpers'
import { configStore, gogConfigStore } from 'src/helpers/electronStores'
import ContextProvider from 'src/state/ContextProvider'
import QuitButton from '../QuitButton'
import './index.css'
Expand All @@ -21,8 +20,8 @@ const { ipcRenderer } = window.require('electron')
export default function SidebarUtils() {
const { t } = useTranslation()
const navigate = useNavigate()
const { platform } = React.useContext(ContextProvider)
const user = configStore.get('userInfo') || gogConfigStore.get('userData')
const { epic, gog, platform } = React.useContext(ContextProvider)
const user = epic.username || gog.username
const isLinux = platform === 'linux'

return (
Expand Down Expand Up @@ -72,7 +71,7 @@ export default function SidebarUtils() {
<div className="Sidebar__itemIcon">
<FontAwesomeIcon icon={faUser} />
</div>
{user.displayName || user.username}
{user}
</button>
<div className="SidebarUtils__dropdownPopup ">
<button
Expand Down
12 changes: 3 additions & 9 deletions src/screens/Game/GamePage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,8 @@ export default function GamePage(): JSX.Element | null {
const [tabToShow, setTabToShow] = useState('infoTab')
const [showModal, setShowModal] = useState({ game: '', show: false })

const {
libraryStatus,
handleGameStatus,
epicLibrary,
gogLibrary,
gameUpdates,
platform
} = useContext(ContextProvider)
const { libraryStatus, handleGameStatus, epic, gog, gameUpdates, platform } =
useContext(ContextProvider)
const gameStatus: GameStatus = libraryStatus.filter(
(game: GameStatus) => game.appName === appName
)[0]
Expand Down Expand Up @@ -136,7 +130,7 @@ export default function GamePage(): JSX.Element | null {
}
}
updateConfig()
}, [isInstalling, isPlaying, appName, epicLibrary, gogLibrary])
}, [isInstalling, isPlaying, appName, epic, gog])

async function handleUpdate() {
await handleGameStatus({
Expand Down
16 changes: 8 additions & 8 deletions src/screens/Library/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export default function Library(): JSX.Element {
refreshing,
category,
filter,
epicLibrary,
gogLibrary,
epic,
gog,
recentGames,
favouriteGames,
libraryTopSection
Expand Down Expand Up @@ -110,7 +110,7 @@ export default function Library(): JSX.Element {
}, [libraryStatus])

// select library and sort
let libraryToShow = category === 'epic' ? epicLibrary : gogLibrary
let libraryToShow = category === 'epic' ? epic.library : gog.library
libraryToShow = libraryToShow.sort(
(a: { title: string }, b: { title: string }) => {
const gameA = a.title.toUpperCase().replace('THE ', '')
Expand Down Expand Up @@ -145,19 +145,19 @@ export default function Library(): JSX.Element {
const favouriteAppNames = favouriteGames.list.map(
(favourite) => favourite.appName
)
epicLibrary.forEach((game) => {
epic.library.forEach((game) => {
if (favouriteAppNames.includes(game.app_name)) favourites.push(game)
})
gogLibrary.forEach((game) => {
gog.library.forEach((game) => {
if (favouriteAppNames.includes(game.app_name)) favourites.push(game)
})
}

const dlcCount = epicLibrary.filter((lib) => lib.install.is_dlc)
const dlcCount = epic.library.filter((lib) => lib.install.is_dlc)
const numberOfGames =
category === 'epic'
? epicLibrary.length - dlcCount.length
: gogLibrary.length
? epic.library.length - dlcCount.length
: gog.library.length

return (
<>
Expand Down
7 changes: 3 additions & 4 deletions src/screens/Login/components/Runner/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,21 @@ interface RunnerProps {
logoutAction: () => any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
alternativeLoginAction?: () => any
refresh: () => void
}

export default function Runner(props: RunnerProps) {
const { t } = useTranslation()
async function handleLogout() {
await props.logoutAction()
window.localStorage.clear()
props.refresh()
// FIXME: only delete local storage relate to one store, or only delete if logged out from both
//window.localStorage.clear()
}
return (
<div className={`runnerWrapper ${props.class}`}>
<div>{props.icon()}</div>
{props.isLoggedIn && (
<div className="userData">
<span>{props.user?.displayName || props.user?.username}</span>
<span>{props.user}</span>
</div>
)}
<div>
Expand Down
12 changes: 6 additions & 6 deletions src/screens/Login/components/SIDLogin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import React, { useState } from 'react'
import React, { useContext, useState } from 'react'
import Info from '@mui/icons-material/Info'
import { useTranslation } from 'react-i18next'
import { loginPage, sidInfoPage } from 'src/helpers'
import './index.css'
import { Autorenew } from '@mui/icons-material'
import ContextProvider from 'src/state/ContextProvider'

const { ipcRenderer, clipboard } = window.require('electron')

interface Props {
backdropClick: () => void
refresh: () => void
}

export default function SIDLogin({ backdropClick, refresh }: Props) {
export default function SIDLogin({ backdropClick }: Props) {
const { epic } = useContext(ContextProvider)
const { t } = useTranslation('login')
const [input, setInput] = useState('')
const [status, setStatus] = useState({
Expand All @@ -23,18 +24,17 @@ export default function SIDLogin({ backdropClick, refresh }: Props) {
const { loading, message } = status

const handleLogin = async (sid: string) => {
await ipcRenderer.invoke('login', sid).then(async (res) => {
await epic.login(sid).then(async (res) => {
setStatus({
loading: true,
message: t('status.loading', 'Loading Game list, please wait')
})
ipcRenderer.send('logInfo', 'Called Login')
console.log(res)
if (res !== 'error') {
if (res === 'done') {
await ipcRenderer.invoke('getUserInfo')
setStatus({ loading: false, message: '' })
backdropClick()
refresh()
} else {
setStatus({ loading: true, message: t('status.error', 'Error') })
setTimeout(() => {
Expand Down
Loading

0 comments on commit 43c1eaa

Please sign in to comment.