Skip to content

Commit 1a64e2b

Browse files
authored
Merge pull request #29 from flavioislima/bug_fixes
BugFixes
2 parents ab72ca0 + 76bf042 commit 1a64e2b

9 files changed

Lines changed: 350 additions & 342 deletions

File tree

public/main.js

Lines changed: 73 additions & 195 deletions
Large diffs are not rendered by default.

public/utils.js

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
const { spawn, exec } = require("child_process");
2+
const promisify = require("util").promisify;
3+
const fs = require('fs')
4+
const {homedir} = require('os')
5+
const execAsync = promisify(exec);
6+
const { fixPathForAsarUnpack } = require("electron-util");
7+
const path = require('path')
8+
9+
const home = homedir();
10+
const legendaryConfigPath = `${home}/.config/legendary`;
11+
const heroicFolder = `${home}/.config/heroic/`;
12+
const heroicConfigPath = `${heroicFolder}config.json`;
13+
const heroicGamesConfigPath = `${heroicFolder}GamesConfig/`
14+
const userInfo = `${legendaryConfigPath}/user.json`;
15+
const heroicInstallPath = `${home}/Games/Heroic`;
16+
const legendaryBin = fixPathForAsarUnpack(path.join(__dirname, "/bin/legendary"));
17+
const icon = fixPathForAsarUnpack(path.join(__dirname, "/icon.png"));
18+
const loginUrl = "https://www.epicgames.com/id/login?redirectUrl=https%3A%2F%2Fwww.epicgames.com%2Fid%2Fapi%2Fredirect";
19+
20+
// check other wine versions installed
21+
const getAlternativeWine = () => {
22+
// TODO: Get all Proton versions
23+
const steamPath = `${home}/.steam/`;
24+
const steamInstallFolder = `${steamPath}root/steamapps/common/`
25+
const steamCompatPath = `${steamPath}root/compatibilitytools.d/`;
26+
const lutrisPath = `${home}/.local/share/lutris`;
27+
const lutrisCompatPath = `${lutrisPath}/runners/wine/`;
28+
let steamWine = [];
29+
let lutrisWine = [];
30+
31+
const defaultWine = {name: 'Wine Default', bin: '/usr/bin/wine'}
32+
33+
if (fs.existsSync(steamCompatPath)) {
34+
steamWine = fs.readdirSync(steamCompatPath).map((version) => {
35+
return {
36+
name: `Steam - ${version}`,
37+
bin: `'${steamCompatPath}${version}/dist/bin/wine64'`,
38+
};
39+
});
40+
}
41+
42+
43+
if (fs.existsSync(steamInstallFolder)) {
44+
fs.readdirSync(steamInstallFolder).forEach((version) => {
45+
if (version.startsWith('Proton')) {
46+
steamWine.push({
47+
name: `Steam - ${version}`,
48+
bin: `'${steamInstallFolder}${version}/dist/bin/wine64'`,
49+
});
50+
}
51+
});
52+
}
53+
54+
if (fs.existsSync(lutrisCompatPath)) {
55+
lutrisWine = fs.readdirSync(lutrisCompatPath).map((version) => {
56+
return {
57+
name: `Lutris - ${version}`,
58+
bin: `'${lutrisCompatPath}${version}/bin/wine64'`,
59+
};
60+
});
61+
}
62+
63+
return [...steamWine, ...lutrisWine, defaultWine];
64+
};
65+
66+
const isLoggedIn = () => fs.readFileSync(userInfo);
67+
68+
const launchGame = async (appName) => {
69+
let envVars = ""
70+
let altWine
71+
let altWinePrefix
72+
const gameConfig = `${heroicGamesConfigPath}${appName}.json`
73+
const globalConfig = heroicConfigPath
74+
let settingsPath = gameConfig
75+
let settingsName = appName
76+
77+
if (!fs.existsSync(gameConfig)) {
78+
settingsPath = globalConfig
79+
settingsName = 'defaultSettings'
80+
}
81+
82+
83+
const settings = JSON.parse(fs.readFileSync(settingsPath))
84+
const { winePrefix, wineVersion, otherOptions } = settings[settingsName]
85+
86+
envVars = otherOptions
87+
88+
if (winePrefix !== "~/.wine") {
89+
altWinePrefix = `${winePrefix}`
90+
}
91+
92+
if (wineVersion.name !== "Wine Default") {
93+
altWine = wineVersion.bin
94+
}
95+
96+
const wine = altWine ? `--wine ${altWine}` : ""
97+
const prefix = altWinePrefix ? `--wine-prefix ${altWinePrefix}` : ""
98+
const command = `${envVars} ${legendaryBin} launch ${appName} ${wine} ${prefix}`
99+
100+
return await execAsync(command)
101+
.then(({ stderr }) => fs.writeFile(`${heroicGamesConfigPath}${appName}-lastPlay.log`, stderr, () => 'done'))
102+
}
103+
104+
const writeDefaultconfig = () => {
105+
const config = {
106+
defaultSettings: {
107+
defaultInstallPath: heroicInstallPath,
108+
wineVersion: {
109+
name: "Wine Default",
110+
bin: "/usr/bin/wine"
111+
},
112+
winePrefix: "~/.wine",
113+
otherOptions: ""
114+
}
115+
}
116+
if (!fs.existsSync(heroicConfigPath)) {
117+
fs.writeFile(heroicConfigPath, JSON.stringify(config, null, 2), () => {
118+
return "done";
119+
});
120+
}
121+
122+
if (!fs.existsSync(heroicGamesConfigPath)) {
123+
fs.mkdir(heroicGamesConfigPath, () => {
124+
return "done";
125+
})
126+
}
127+
}
128+
129+
const writeGameconfig = async (game) => {
130+
const { wineVersion, winePrefix, otherOptions } = JSON.parse(fs.readFileSync(heroicConfigPath)).defaultSettings
131+
132+
const config = {
133+
[game]: {
134+
wineVersion,
135+
winePrefix,
136+
otherOptions
137+
}
138+
}
139+
140+
if (!fs.existsSync(`${heroicGamesConfigPath}${game}.json`)) {
141+
await Promise.resolve(fs.writeFileSync(`${heroicGamesConfigPath}${game}.json`, JSON.stringify(config, null, 2), () => {
142+
return "done";
143+
}));
144+
}
145+
}
146+
147+
148+
module.exports = {
149+
getAlternativeWine,
150+
isLoggedIn,
151+
launchGame,
152+
writeDefaultconfig,
153+
writeGameconfig,
154+
userInfo,
155+
heroicConfigPath,
156+
heroicFolder,
157+
heroicGamesConfigPath,
158+
legendaryConfigPath,
159+
legendaryBin,
160+
icon,
161+
loginUrl
162+
}

src/components/Settings.tsx

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ interface Path {
3030
}
3131

3232
// TODO: Refactor this component in smaller components
33+
// TODO: add option to add Custom wine
34+
// TODO: add feedback when launching winecfg and winetricks
3335

3436
export default function Settings() {
3537
const [wineVersion, setWineversion] = useState({
@@ -40,7 +42,6 @@ export default function Settings() {
4042
const [defaultInstallPath, setDefaultInstallPath] = useState("");
4143
const [otherOptions, setOtherOptions] = useState("");
4244
const [altWine, setAltWine] = useState([] as WineProps[]);
43-
const [saved, setSaved] = useState(false)
4445

4546
const { appName } = useParams() as RouteParams;
4647
const isDefault = appName === 'default'
@@ -64,11 +65,6 @@ export default function Settings() {
6465
);
6566
}, [settings, appName]);
6667

67-
useEffect(() => {
68-
// TODO: Save settings automatically
69-
setSaved(false)
70-
}, [altWine, otherOptions, defaultInstallPath, wineVersion])
71-
7268
const callTools = (tool: string) =>
7369
ipcRenderer.send("callTool", {
7470
tool,
@@ -94,6 +90,11 @@ export default function Settings() {
9490
}
9591

9692
const settingsToSave = isDefault ? GlobalSettings : GameSettings
93+
94+
useEffect(() => {
95+
// TODO: Save settings automatically
96+
writeConfig([appName, settingsToSave])
97+
}, [winePrefix, defaultInstallPath, altWine, otherOptions, appName, settingsToSave])
9798

9899
return (
99100
<>
@@ -207,18 +208,8 @@ export default function Settings() {
207208
</div>
208209
</div>
209210
<div className="save">
210-
<button
211-
className="button is-success"
212-
onClick={() => {
213-
writeConfig([appName, settingsToSave])
214-
return setSaved(true)
215-
}
216-
}
217-
>
218-
Save Settings
219-
</button>
220-
<span className="material-icons" style={ saved ? {color: '#0BD58C', opacity: 1 } : {color: '#0BD58C', opacity: 0.4 }}>
221-
check_circle_outline
211+
<span style={ {color: '#0BD58C', opacity: 1 }}>
212+
Settings are saved automatically
222213
</span>
223214
</div>
224215
</div>

src/components/UI/GameCard.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@ interface Card {
1111
const GameCard = ({ cover, title, appName, isInstalled }: Card) => {
1212
return (
1313
<Link
14-
className="gameCard "
14+
className="gameCard"
1515
to={{
1616
pathname: `/gameconfig/${appName}`
1717
}}
1818
>
19-
<img alt="cover-art" src={cover} className="gameImg" />
19+
<img
20+
alt="cover-art"
21+
src={cover}
22+
style={{ filter: isInstalled ? 'none' : 'grayscale(0.9)'}}
23+
className="gameImg" />
2024
<div className="gameTitle">
2125
<span>{title}</span>
2226
<i

src/components/UI/GamePage.tsx

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,13 @@ const {
2121
} = remote;
2222

2323
// This component is becoming really complex and it needs to be refactored in smaller ones
24-
interface Card {
25-
location: any;
26-
}
2724

2825
interface RouteParams {
2926
appName: string;
3027
}
3128

32-
export default function GamePage({ location }: Card) {
33-
const [gameInfo, setGameInfo] = useState({} as Game);
34-
const [progress, setProgress] = useState("0.00");
35-
const [uninstalling, setUninstalling] = useState(false);
36-
const [installPath, setInstallPath] = useState("default");
29+
export default function GamePage() {
30+
const { appName } = useParams() as RouteParams;
3731

3832
const {
3933
handleInstalling,
@@ -43,11 +37,13 @@ export default function GamePage({ location }: Card) {
4337
playing,
4438
} = useContext(ContextProvider);
4539

46-
const { appName } = useParams() as RouteParams;
40+
const [gameInfo, setGameInfo] = useState({} as Game);
41+
const [progress, setProgress] = useState("0.00");
42+
const [uninstalling, setUninstalling] = useState(false);
43+
const [installPath, setInstallPath] = useState("default");
44+
45+
const isInstalling = Boolean(installing.filter((game) => game === appName).length)
4746

48-
const isInstalling = Boolean(
49-
installing.filter((game) => game === appName).length
50-
);
5147
const isPlaying = Boolean(playing.filter((game) => game === appName).length);
5248

5349
useEffect(() => {
@@ -62,11 +58,11 @@ export default function GamePage({ location }: Card) {
6258
const progressInterval = setInterval(() => {
6359
if (isInstalling) {
6460
ipcRenderer.send("requestGameProgress", appName);
65-
ipcRenderer.on("requestedOutput", (event: any, progress: string) =>
66-
setProgress(progress)
61+
ipcRenderer.on("requestedOutput", (event: any, out: string) =>
62+
setProgress(out)
6763
);
6864
}
69-
}, 2000);
65+
}, 1000);
7066
return () => clearInterval(progressInterval);
7167
}, [isInstalling, appName]);
7268

@@ -244,7 +240,8 @@ export default function GamePage({ location }: Card) {
244240
if (isInstalled) {
245241
setUninstalling(true);
246242
await legendary(`uninstall ${appName}`);
247-
return setUninstalling(false);
243+
setUninstalling(false);
244+
return refresh()
248245
}
249246

250247
if (installPath === "default") {

src/components/UI/Header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useContext } from "react";
2-
import { Link, useHistory } from "react-router-dom";
2+
import { useHistory } from "react-router-dom";
33
import ContextProvider from '../../state/ContextProvider';
44
import ToggleSwitch from './ToggleSwitch';
55

src/components/UI/SearchBar.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ContextProvider from '../../state/ContextProvider';
44
export default function SearchBar() {
55
const { handleSearch } = useContext(ContextProvider)
66
const [textValue, setTextValue] = useState('')
7-
7+
88
return (
99
<div className="SearchBar">
1010
<span
@@ -19,12 +19,12 @@ export default function SearchBar() {
1919
}}
2020
placeholder={"Enter the game name here..."}
2121
/>
22-
<span
22+
{textValue.length > 0 && <span
2323
onClick={() => {
2424
setTextValue('')
2525
handleSearch('')
2626
}}
27-
className="material-icons close">close</span>
27+
className="material-icons close">close</span>}
2828
</div>
2929
);
3030
}

0 commit comments

Comments
 (0)