forked from Berry-Dash/launcher
Add wine support back for Linux
This commit is contained in:
@@ -255,7 +255,14 @@ async fn download(
|
|||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn launch_game(app: AppHandle, name: String, executable: String, display_name: String) {
|
fn launch_game(
|
||||||
|
app: AppHandle,
|
||||||
|
name: String,
|
||||||
|
executable: String,
|
||||||
|
display_name: String,
|
||||||
|
use_wine: bool,
|
||||||
|
wine_command: String,
|
||||||
|
) {
|
||||||
let game_folder = app
|
let game_folder = app
|
||||||
.path()
|
.path()
|
||||||
.app_local_data_dir()
|
.app_local_data_dir()
|
||||||
@@ -266,10 +273,12 @@ fn launch_game(app: AppHandle, name: String, executable: String, display_name: S
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let exe_path = game_folder.join(&executable);
|
||||||
|
|
||||||
//if already running on macos, it'll auto take the user to that proccess
|
//if already running on macos, it'll auto take the user to that proccess
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||||
{
|
{
|
||||||
if is_running_by_path(&game_folder.join(&executable)) {
|
if !use_wine && is_running_by_path(&exe_path) {
|
||||||
app.dialog()
|
app.dialog()
|
||||||
.message(format!(
|
.message(format!(
|
||||||
"{} is already running, if this doesn't seem true, try to kill the proccess.",
|
"{} is already running, if this doesn't seem true, try to kill the proccess.",
|
||||||
@@ -282,6 +291,23 @@ fn launch_game(app: AppHandle, name: String, executable: String, display_name: S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
if use_wine {
|
||||||
|
let quoted_path = format!("\"{}\"", exe_path.to_string_lossy());
|
||||||
|
let cmd = wine_command.replace("%path%", "ed_path);
|
||||||
|
|
||||||
|
Command::new("bash")
|
||||||
|
.arg("-c")
|
||||||
|
.arg(cmd)
|
||||||
|
.current_dir(&game_folder)
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if platform() == "macos" {
|
if platform() == "macos" {
|
||||||
Command::new("open")
|
Command::new("open")
|
||||||
.arg(&executable)
|
.arg(&executable)
|
||||||
@@ -289,7 +315,7 @@ fn launch_game(app: AppHandle, name: String, executable: String, display_name: S
|
|||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
Command::new(&game_folder.join(&executable))
|
Command::new(&exe_path)
|
||||||
.current_dir(&game_folder)
|
.current_dir(&game_folder)
|
||||||
.spawn()
|
.spawn()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.input-field {
|
.input-field {
|
||||||
@apply border-2 border-(--col4) rounded-md bg-(--col2) p-2 px-4 focus:border-blue-600 transition-colors;
|
@apply border-2 border-(--col4) rounded-md bg-(--col2) py-1 px-2 focus:bg-(--col3) focus:border-(--col6) transition-colors w-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-info-item {
|
.entry-info-item {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import { invoke } from '@tauri-apps/api/core'
|
|||||||
import { useGlobal } from '../GlobalProvider'
|
import { useGlobal } from '../GlobalProvider'
|
||||||
import { useSearchParams } from 'next/navigation'
|
import { useSearchParams } from 'next/navigation'
|
||||||
import { platform } from '@tauri-apps/plugin-os'
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
|
import { faWarning } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||||
|
|
||||||
export default function Installs () {
|
export default function Installs () {
|
||||||
const {
|
const {
|
||||||
@@ -71,6 +73,12 @@ export default function Installs () {
|
|||||||
.filter(v => {
|
.filter(v => {
|
||||||
const info = getVersionInfo(v)
|
const info = getVersionInfo(v)
|
||||||
if (!info) return false
|
if (!info) return false
|
||||||
|
if (
|
||||||
|
platform() === 'linux' &&
|
||||||
|
info.wine &&
|
||||||
|
!normalConfig?.settings.useWineOnUnixWhenNeeded
|
||||||
|
)
|
||||||
|
return false
|
||||||
return info.game === Number(params.get('id') || 0)
|
return info.game === Number(params.get('id') || 0)
|
||||||
})
|
})
|
||||||
.map((entry, i) => (
|
.map((entry, i) => (
|
||||||
@@ -95,11 +103,19 @@ export default function Installs () {
|
|||||||
invoke('launch_game', {
|
invoke('launch_game', {
|
||||||
name: verInfo.id,
|
name: verInfo.id,
|
||||||
executable: verInfo.executable,
|
executable: verInfo.executable,
|
||||||
displayName: `${gameInfo.name} v${verInfo.versionName}`
|
displayName: `${gameInfo.name} v${verInfo.versionName}`,
|
||||||
|
useWine: !!(
|
||||||
|
platform() === 'linux' &&
|
||||||
|
verInfo.wine &&
|
||||||
|
normalConfig?.settings.useWineOnUnixWhenNeeded
|
||||||
|
),
|
||||||
|
wineCommand: normalConfig?.settings.wineOnUnixCommand
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
onContextMenu={e => {
|
onContextMenu={e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
if (normalConfig?.settings.useLegacyInteractButtons) return
|
||||||
|
|
||||||
setManagingVersion(entry)
|
setManagingVersion(entry)
|
||||||
setPopupMode(2)
|
setPopupMode(2)
|
||||||
setShowPopup(true)
|
setShowPopup(true)
|
||||||
@@ -112,18 +128,37 @@ export default function Installs () {
|
|||||||
{getVersionInfo(entry)?.versionName}
|
{getVersionInfo(entry)?.versionName}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div className='flex gap-2 absolute left-0 bottom-0'>
|
||||||
<div
|
<div
|
||||||
className='entry-info-item absolute left-0 bottom-0'
|
className='entry-info-item'
|
||||||
title='The date the game was installed in MM/dd/yyyy format'
|
title='The date the game was installed in MM/dd/yyyy format'
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
Installed{' '}
|
Installed{' '}
|
||||||
{format(
|
{format(
|
||||||
new Date(downloadedVersionsConfig.timestamps[entry]),
|
new Date(
|
||||||
|
downloadedVersionsConfig.timestamps[entry]
|
||||||
|
),
|
||||||
'MM/dd/yyyy'
|
'MM/dd/yyyy'
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className='entry-info-item'
|
||||||
|
title='This version is using wine. It cannot be guarenteed to work fully and might not work at all.'
|
||||||
|
hidden={
|
||||||
|
!(
|
||||||
|
platform() === 'linux' &&
|
||||||
|
getVersionInfo(entry)?.wine
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faWarning} color='#ffc800' />
|
||||||
|
<p>Uses wine</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className='flex gap-2 absolute right-0 bottom-0'>
|
<div className='flex gap-2 absolute right-0 bottom-0'>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -89,6 +89,13 @@ export default function RootLayout ({
|
|||||||
return serverVersionList.versions
|
return serverVersionList.versions
|
||||||
.filter(v => !downloadedVersionsConfig?.list.includes(v.id))
|
.filter(v => !downloadedVersionsConfig?.list.includes(v.id))
|
||||||
.filter(v => {
|
.filter(v => {
|
||||||
|
if (
|
||||||
|
platform() === 'linux' &&
|
||||||
|
v.wine &&
|
||||||
|
!normalConfig.settings.useWineOnUnixWhenNeeded
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
|
||||||
if (game && v.game != game) return false
|
if (game && v.game != game) return false
|
||||||
if (downloadProgress.length != 0) {
|
if (downloadProgress.length != 0) {
|
||||||
return !downloadProgress.some(d => d.version === v.id)
|
return !downloadProgress.some(d => d.version === v.id)
|
||||||
@@ -133,13 +140,21 @@ export default function RootLayout ({
|
|||||||
} | null {
|
} | null {
|
||||||
if (!downloadedVersionsConfig || !serverVersionList) return null
|
if (!downloadedVersionsConfig || !serverVersionList) return null
|
||||||
|
|
||||||
const installed = downloadedVersionsConfig.list.filter(
|
const allowWine =
|
||||||
v => getGameInfo(getVersionInfo(v)?.game)?.id === gameId
|
platform() !== 'linux' || normalConfig?.settings.useWineOnUnixWhenNeeded
|
||||||
).length
|
|
||||||
|
|
||||||
const total = serverVersionList.versions.filter(
|
const installed = downloadedVersionsConfig.list.filter(v => {
|
||||||
v => getGameInfo(v?.game)?.id === gameId
|
const info = getVersionInfo(v)
|
||||||
).length
|
if (!info) return false
|
||||||
|
if (info.wine && !allowWine) return false
|
||||||
|
return getGameInfo(info.game)?.id === gameId
|
||||||
|
}).length
|
||||||
|
|
||||||
|
const total = serverVersionList.versions.filter(v => {
|
||||||
|
if (!v) return false
|
||||||
|
if (v.wine && !allowWine) return false
|
||||||
|
return getGameInfo(v.game)?.id === gameId
|
||||||
|
}).length
|
||||||
|
|
||||||
return { installed, total }
|
return { installed, total }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ export default function Installs () {
|
|||||||
<div
|
<div
|
||||||
className='entry-info-item'
|
className='entry-info-item'
|
||||||
title='The amount of versions installed of this game in installed/installable format.'
|
title='The amount of versions installed of this game in installed/installable format.'
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<p>
|
<p>
|
||||||
{(() => {
|
{(() => {
|
||||||
@@ -103,6 +104,7 @@ export default function Installs () {
|
|||||||
className='entry-info-item'
|
className='entry-info-item'
|
||||||
hidden={!i.official}
|
hidden={!i.official}
|
||||||
title='This game is official.'
|
title='This game is official.'
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faCheck} color='#19c84b' />
|
<FontAwesomeIcon icon={faCheck} color='#19c84b' />
|
||||||
<p>Official</p>
|
<p>Official</p>
|
||||||
@@ -115,6 +117,7 @@ export default function Installs () {
|
|||||||
? 'This game is verified to be safe'
|
? 'This game is verified to be safe'
|
||||||
: 'This game is not verified to be save. Proceed with caution.'
|
: 'This game is not verified to be save. Proceed with caution.'
|
||||||
}
|
}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={i.verified ? faShieldHalved : faWarning}
|
icon={i.verified ? faShieldHalved : faWarning}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Setting } from '../componets/Setting'
|
|||||||
import { writeNormalConfig } from '../util/BazookaManager'
|
import { writeNormalConfig } from '../util/BazookaManager'
|
||||||
import { useGlobal } from '../GlobalProvider'
|
import { useGlobal } from '../GlobalProvider'
|
||||||
import { copyToClipboard } from '../util/Clipboard'
|
import { copyToClipboard } from '../util/Clipboard'
|
||||||
|
import { platform } from '@tauri-apps/plugin-os'
|
||||||
|
|
||||||
export default function Settings () {
|
export default function Settings () {
|
||||||
const [allowNotifications, setAllowNotifications] = useState(false)
|
const [allowNotifications, setAllowNotifications] = useState(false)
|
||||||
@@ -12,6 +13,8 @@ export default function Settings () {
|
|||||||
useState(false)
|
useState(false)
|
||||||
const [useLegacyInteractButtons, setUseLegacyInteractButtons] =
|
const [useLegacyInteractButtons, setUseLegacyInteractButtons] =
|
||||||
useState(false)
|
useState(false)
|
||||||
|
const [useWineOnUnixWhenNeeded, setUseWineOnUnixWhenNeeded] = useState(false)
|
||||||
|
const [wineOnUnixCommand, setWineOnUnixCommand] = useState('wine %path%')
|
||||||
const [theme, setTheme] = useState(0)
|
const [theme, setTheme] = useState(0)
|
||||||
|
|
||||||
const [loaded, setLoaded] = useState(false)
|
const [loaded, setLoaded] = useState(false)
|
||||||
@@ -27,6 +30,10 @@ export default function Settings () {
|
|||||||
setUseLegacyInteractButtons(
|
setUseLegacyInteractButtons(
|
||||||
normalConfig.settings.useLegacyInteractButtons
|
normalConfig.settings.useLegacyInteractButtons
|
||||||
)
|
)
|
||||||
|
setUseWineOnUnixWhenNeeded(
|
||||||
|
normalConfig.settings.useWineOnUnixWhenNeeded
|
||||||
|
)
|
||||||
|
setWineOnUnixCommand(normalConfig.settings.wineOnUnixCommand)
|
||||||
setTheme(normalConfig.settings.theme)
|
setTheme(normalConfig.settings.theme)
|
||||||
setLoaded(true)
|
setLoaded(true)
|
||||||
break
|
break
|
||||||
@@ -114,6 +121,38 @@ export default function Settings () {
|
|||||||
}}
|
}}
|
||||||
title='Enable the legacy method of using the installs/launch/manage buttons. In the future this setting may be removed so try and get used to the new method.'
|
title='Enable the legacy method of using the installs/launch/manage buttons. In the future this setting may be removed so try and get used to the new method.'
|
||||||
/>
|
/>
|
||||||
|
<Setting
|
||||||
|
label='Use wine when needed to launch games'
|
||||||
|
value={useWineOnUnixWhenNeeded}
|
||||||
|
onChange={async () => {
|
||||||
|
while (normalConfig != null) {
|
||||||
|
setUseWineOnUnixWhenNeeded(!useWineOnUnixWhenNeeded)
|
||||||
|
normalConfig.settings.useWineOnUnixWhenNeeded =
|
||||||
|
!useWineOnUnixWhenNeeded
|
||||||
|
await writeNormalConfig(normalConfig)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className={platform() == 'linux' ? '' : 'hidden'}
|
||||||
|
/>
|
||||||
|
<p hidden={!(platform() == 'linux' && useWineOnUnixWhenNeeded)}>
|
||||||
|
Wine Command:
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
type='text'
|
||||||
|
value={wineOnUnixCommand}
|
||||||
|
onChange={async e => {
|
||||||
|
while (normalConfig != null) {
|
||||||
|
setWineOnUnixCommand(e.target.value)
|
||||||
|
normalConfig.settings.wineOnUnixCommand = e.target.value
|
||||||
|
await writeNormalConfig(normalConfig)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className={`input-field my-1 ${
|
||||||
|
platform() == 'linux' && useWineOnUnixWhenNeeded ? '' : 'hidden'
|
||||||
|
}`}
|
||||||
|
></input>
|
||||||
<div title='The theme you want the launcher to use.'>
|
<div title='The theme you want the launcher to use.'>
|
||||||
<label className='text-lg'>Theme:</label>
|
<label className='text-lg'>Theme:</label>
|
||||||
<select
|
<select
|
||||||
|
|||||||
@@ -9,4 +9,5 @@ export interface GameVersion {
|
|||||||
size: number
|
size: number
|
||||||
place: number
|
place: number
|
||||||
changelog: string
|
changelog: string
|
||||||
|
wine: number | undefined
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ export class SettingsType {
|
|||||||
public allowNotifications: boolean = true,
|
public allowNotifications: boolean = true,
|
||||||
public alwaysShowGamesInSidebar: boolean = true,
|
public alwaysShowGamesInSidebar: boolean = true,
|
||||||
public useLegacyInteractButtons: boolean = false,
|
public useLegacyInteractButtons: boolean = false,
|
||||||
|
public useWineOnUnixWhenNeeded: boolean = false,
|
||||||
|
public wineOnUnixCommand: string = 'wine %path%',
|
||||||
public theme: number = 0
|
public theme: number = 0
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user