fix: Force image rendering with GPU on WebKitGTK

fix: Pluralisation of function secondsToWords
feat: Screenshot list works (needs better functionality though)
This commit is contained in:
LynithDev 2024-08-08 19:12:28 +02:00
parent f289a5c768
commit dfb8edd069
7 changed files with 90 additions and 36 deletions

View file

@ -182,3 +182,16 @@ pub async fn upload_log(uuid: Uuid, log_name: String) -> Result<String, String>
let id = logger::upload_log(&cluster.cluster_path(), log).await?;
Ok(id)
}
#[specta::specta]
#[tauri::command]
pub async fn get_screenshots(uuid: Uuid) -> Result<Vec<String>, String> {
let cluster = onelauncher::cluster::get_by_uuid(uuid, None)
.await?
.ok_or("cluster not found")?;
let screenshots = cluster::content::screenshots::get_screenshots(&cluster.cluster_path())
.await?;
Ok(screenshots)
}

View file

@ -39,6 +39,7 @@ macro_rules! collect_commands {
get_cluster_logs,
get_cluster_log,
upload_log,
get_screenshots,
// Processor
get_running_clusters,
get_processes_by_path,

View file

@ -58,8 +58,7 @@
"enable": true,
"scope": {
"allow": [
"$DATA/OneLauncher/metadata/caches/icons/*",
"$DATA/OneLauncher/db/**",
"$DATA/OneLauncher/**",
"$RESOURCE/**"
],
"deny": ["$DATA/OneLauncher/db/*.stronghold"]

View file

@ -24,6 +24,14 @@ img {
}
/* end lynith's native experience (tm) */
/* lynith's epic webkit gtk <=2.44 fixer */
body[data-platform="linux"] img {
/* Forces webkit gtk to use the GPU for image rendering, should speed up loading of some pages. Temporary until Tauri updates to at least 2.45
2.45 is the first version to use Skia for rendering, which prioritises the GPU over the CPU unlike Cairo */
@apply transform-gpu;
}
/* end lynith's epic webkit gtk <=2.44 fixer */
h1 { @apply text-2xl font-semibold; line-height: 1.5 !important; }
h2 { @apply text-xxl font-semibold; line-height: 1.25 !important; }
h3 { @apply text-xl font-medium; }

View file

@ -1,9 +1,9 @@
/* @refresh reload */
import { render } from 'solid-js/web';
import './imports';
import { Route, Router } from '@solidjs/router';
import { bridge } from './imports';
import App from './ui/App';
import HomePage from './ui/pages/Home';
import UpdatesPage from './ui/pages/Updates';
@ -11,6 +11,8 @@ import ClusterRoot from '~ui/pages/cluster/ClusterRoot';
import SettingsRoot from '~ui/pages/settings/SettingsRoot';
import BrowserRoot from '~ui/pages/browser/BrowserRoot';
document.body.setAttribute('data-platform', bridge.PROGRAM_INFO.platform);
render(() => (
<Router root={App}>
<Route path="/" component={HomePage} />

View file

@ -1,43 +1,74 @@
import { For } from 'solid-js';
import { convertFileSrc } from '@tauri-apps/api/core';
import { open } from '@tauri-apps/plugin-shell';
import { LinkExternal01Icon } from '@untitled-theme/icons-solid';
import { join } from 'pathe';
import { For, Show } from 'solid-js';
import { bridge } from '~imports';
import Button from '~ui/components/base/Button';
import ScrollableContainer from '~ui/components/ScrollableContainer';
import Sidebar from '~ui/components/Sidebar';
const list = Array<Screenshot>(19).fill({
date_taken: Math.floor(Date.now() / 1000),
path: 'https://www.researchgate.net/publication/301648368/figure/fig2/AS:667842240315400@1536237406360/A-screenshot-from-Minecraft-a-popular-video-game-which-poses-a-challenging-lifelong.ppm',
});
// TODO: Make sure the screenshots in the list are downscaled, grid / container can get laggy on low end devices
interface Screenshot {
path: string;
date_taken: number;
};
import useClusterContext from '~ui/hooks/useCluster';
import useCommand from '~ui/hooks/useCommand';
import useSettingsContext from '~ui/hooks/useSettings';
function ClusterScreenshots() {
const { settings } = useSettingsContext();
const [cluster] = useClusterContext();
const [list] = useCommand(bridge.commands.getScreenshots, cluster()!.uuid!);
function openFolder() {
open(join(settings().config_dir || '', 'clusters', cluster()?.path || '', 'screenshots'));
}
return (
<Sidebar.Page>
<h1>Screenshots</h1>
<ScrollableContainer>
<div class="grid grid-cols-[repeat(auto-fill,minmax(350px,1fr))] w-full gap-2">
<For each={list}>
{screenshot => (
<ScreenshotEntry {...screenshot} />
)}
</For>
</div>
<Show
fallback={<div class="text-gray-400">No screenshots found. Press F2 in game to take a screenshot!</div>}
when={list() !== undefined && list()!.length > 0}
>
<div class="grid grid-cols-[repeat(auto-fill,minmax(350px,1fr))] w-full gap-2 transform-gpu">
<For each={list()!}>
{screenshot => (
<ScreenshotEntry path={screenshot} cluster_path={cluster()?.path || ''} />
)}
</For>
</div>
</Show>
</ScrollableContainer>
<div class="flex flex-row justify-end items-end mt-2">
<Button
buttonStyle="primary"
iconLeft={<LinkExternal01Icon />}
children="Open Folder"
onClick={openFolder}
/>
</div>
</Sidebar.Page>
);
}
export default ClusterScreenshots;
function ScreenshotEntry(props: Screenshot) {
function ScreenshotEntry(props: { path: string; cluster_path: string }) {
const { settings } = useSettingsContext();
const dir = () => join(settings().config_dir || '', 'clusters', props.cluster_path, 'screenshots');
const pathSrc = () => convertFileSrc(join(dir(), props.path));
function onClick() {
// TODO: Probably make a cool image viewer or something
open(dir());
}
return (
<div class="bg-component-bg hover:bg-component-bg-hover hover:opacity-80 active:bg-component-bg-pressed p-3 gap-3 rounded-xl flex flex-col items-center">
{/* <div> */}
<img src={props.path} alt={props.path} class="aspect-ratio-video w-full rounded-lg" />
{/* </div> */}
<div
class="bg-component-bg hover:bg-component-bg-hover hover:opacity-80 active:bg-component-bg-pressed p-3 gap-3 rounded-xl flex flex-col items-center"
onClick={onClick}
>
<img src={pathSrc()} alt={props.path} class="aspect-ratio-video w-full rounded-lg" />
</div>
);
}

View file

@ -54,21 +54,21 @@ export function secondsToWords(seconds: number | bigint, plural: boolean = true)
const func = (n: number) => {
if (n < 60)
return `${n} seconds`;
return `${n} second`;
else if (n < (60 * 60))
return `${Math.floor(n / 60)} minutes`;
return `${Math.floor(n / 60)} minute`;
else if (n < (60 * 60 * 24))
return `${Math.floor(n / (60 * 60))} hours`;
return `${Math.floor(n / (60 * 60))} hour`;
else if (n < (60 * 60 * 24 * 7))
return `${Math.floor(n / (60 * 60 * 24))} days`;
return `${Math.floor(n / (60 * 60 * 24))} day`;
else if (n < (60 * 60 * 24 * 30))
return `${Math.floor(n / (60 * 60 * 24 * 7))} weeks`;
return `${Math.floor(n / (60 * 60 * 24 * 7))} week`;
else if (n < (60 * 60 * 24 * 365))
return `${Math.floor(n / (60 * 60 * 24 * 30))} months`;
return `${Math.floor(n / (60 * 60 * 24 * 30))} month`;
else if (n < (60 * 60 * 24 * 365 * 10))
return `${Math.floor(n / (60 * 60 * 24 * 365))} years`;
return `${Math.floor(n / (60 * 60 * 24 * 365))} year`;
return `${n} seconds`; // Hmmmmmm
return `${n} second`; // Hmmmmmm
};
const str = func(n);