Skip to content

Commit 2f80658

Browse files
committed
feat: Somewhat working Browser UI
1 parent 170762f commit 2f80658

File tree

11 files changed

+198
-93
lines changed

11 files changed

+198
-93
lines changed

apps/desktop/src-tauri/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ fn main() {
2626
"set_settings",
2727
// Metadata
2828
"get_minecraft_versions",
29+
// Package
30+
"random_mods",
31+
"get_mod",
32+
"download_mod",
2933
// Other
3034
"get_program_info",
3135
]),

apps/desktop/src-tauri/permissions/onelauncher/default.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ permissions = [
2727
# Metadata
2828
"allow-get-minecraft-versions",
2929

30+
# Package
31+
"allow-random-mods",
32+
"allow-get-mod",
33+
"allow-download-mod",
34+
3035
# Other
3136
"allow-get-program-info",
3237
]

apps/desktop/src-tauri/src/api/commands.rs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use std::path::PathBuf;
22

33
use interpulse::api::minecraft::Version;
44
use onelauncher::constants::{NATIVE_ARCH, TARGET_OS, VERSION};
5-
use onelauncher::data::{Loader, MinecraftCredentials, PackageData, Settings};
5+
use onelauncher::data::{Loader, ManagedPackage, MinecraftCredentials, PackageData, Settings};
6+
use onelauncher::package::content;
67
use onelauncher::store::{Cluster, ClusterPath, MinecraftLogin};
78
use onelauncher::{cluster, minecraft, processor, settings};
89
use serde::{Deserialize, Serialize};
@@ -40,6 +41,10 @@ macro_rules! collect_commands {
4041
set_settings,
4142
// Metadata
4243
get_minecraft_versions,
44+
// Package
45+
random_mods,
46+
get_mod,
47+
download_mod,
4348
// Other
4449
get_program_info,
4550
])
@@ -244,8 +249,34 @@ pub async fn remove_user(uuid: Uuid) -> Result<(), String> {
244249
Ok(minecraft::remove_user(uuid).await?)
245250
}
246251

247-
// #[specta::specta]
248-
// #[tauri::command]
249-
// pub async fn searchMods(query: String) -> Result<Vec<ModrinthMod>, String> {
250-
// // Ok(onelauncher::api::)
251-
// }
252+
#[specta::specta]
253+
#[tauri::command]
254+
pub async fn random_mods() -> Result<Vec<ManagedPackage>, String> {
255+
let provider = content::Providers::Modrinth;
256+
Ok(provider.list().await?)
257+
}
258+
259+
#[specta::specta]
260+
#[tauri::command]
261+
pub async fn get_mod(project_id: String) -> Result<ManagedPackage, String> {
262+
let provider = content::Providers::Modrinth;
263+
Ok(provider.get(&project_id).await?)
264+
}
265+
266+
#[specta::specta]
267+
#[tauri::command]
268+
pub async fn download_mod(cluster_id: Uuid, version_id: String) -> Result<(), String> {
269+
let cluster = cluster::get_by_uuid(cluster_id, None).await?.ok_or("cluster not found")?;
270+
let provider = content::Providers::Modrinth;
271+
let game_version = cluster.meta.mc_version.clone();
272+
273+
provider.get_version_for_game_version(&version_id, &game_version)
274+
.await?
275+
.files
276+
.first()
277+
.ok_or("no files found")?
278+
.download_to_cluster(&cluster)
279+
.await?;
280+
281+
Ok(())
282+
}

apps/desktop/src/types/global.d.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,4 @@ declare namespace globalThis {
2121
// }
2222

2323
// type Result = UnionToArray<keyof typeof Example>['length'] // = 5
24-
}
25-
26-
// TODO remove in place for specta-generated types
27-
interface Mod {
28-
id: string;
29-
name: string;
30-
description: string;
31-
author: string;
32-
icon_url: string;
33-
provider: Provider;
34-
page_url: string;
35-
downloads: number;
36-
ratings: number;
3724
}

apps/desktop/src/ui/components/content/ModCard.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Download01Icon, HeartIcon } from '@untitled-theme/icons-solid';
22
import { useNavigate } from '@solidjs/router';
33
import { abbreviateNumber } from '../../../utils/primitives';
44
import BrowserMod from '~ui/pages/browser/BrowserMod';
5+
import type { ManagedPackage } from '~bindings';
56

67
// TODO: Remove in place for specta generated types
78
export enum Provider {
@@ -11,37 +12,37 @@ export enum Provider {
1112
Skyclient,
1213
}
1314

14-
function ModCard(props: Mod) {
15+
function ModCard(props: ManagedPackage) {
1516
const navigate = useNavigate();
1617

1718
function redirect() {
1819
navigate(BrowserMod.getUrl({
1920
id: props.id,
20-
provider: Provider[props.provider] || 'unknown',
21+
provider: 'modrinth',
2122
}));
2223
}
2324

2425
return (
2526
<div onClick={redirect} class="flex flex-col overflow-hidden rounded-lg bg-component-bg max-w-53 min-w-53 w-full max-h-68 min-h-68 h-full">
2627
<div class="relative h-28 overflow-hidden flex justify-center items-center">
27-
<img class="absolute filter-blur-xl z-0 max-w-none w-7/6" src={props.icon_url} alt={`Icon for ${props.name}`} />
28-
<img class="relative w-2/5 aspect-ratio-square z-1 rounded-2xl" src={props.icon_url} alt={`Icon for ${props.name}`} />
28+
<img class="absolute filter-blur-xl z-0 max-w-none w-7/6" src={props.icon_url || ''} alt={`Icon for ${props.title}`} />
29+
<img class="relative w-2/5 aspect-ratio-square z-1 rounded-md image-render-auto" src={props.icon_url || ''} alt={`Icon for ${props.title}`} />
2930
</div>
3031
<div class="flex flex-col flex-1 p-3 gap-4">
3132
<div class="flex flex-col gap-2">
32-
<h5 class="font-medium text-fg-primary">{props.name}</h5>
33+
<h5 class="font-medium text-fg-primary">{props.title}</h5>
3334
<p class="text-fg-secondary text-xs">
3435
By
3536
{' '}
36-
<span class="text-fg-primary">{props.author}</span>
37+
<span class="text-fg-primary">Author TODO</span>
3738
{' '}
3839
on
3940
{' '}
40-
{Provider[props.provider]}
41+
Modrinth
4142
</p>
4243
</div>
4344

44-
<p class="text-fg-secondary text-sm flex-1">{props.description}</p>
45+
<p class="text-fg-secondary text-sm flex-1 max-h-13 overflow-hidden line-height-snug">{props.description}</p>
4546

4647
<div class="flex flex-row gap-4 text-xs">
4748
<div class="flex flex-row items-center gap-2">
@@ -51,7 +52,7 @@ function ModCard(props: Mod) {
5152

5253
<div class="flex flex-row items-center gap-2">
5354
<HeartIcon class="w-4 h-4" />
54-
{abbreviateNumber(props.ratings)}
55+
{abbreviateNumber(props.followers)}
5556
</div>
5657
</div>
5758
</div>
Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
import { type Context, type ParentProps, createContext, useContext } from 'solid-js';
1+
// import { type Context, type ParentProps, createContext, useContext } from 'solid-js';
22

3-
interface BrowserContextType {
4-
getMod: (id: string) => void;
5-
getMods: (category: string) => void;
6-
};
3+
// interface BrowserContextType {
4+
// getMod: (id: string) => void;
5+
// getMods: (category: string) => void;
6+
// };
77

8-
const BrowserContext = createContext() as Context<BrowserContextType>;
8+
// const BrowserContext = createContext() as Context<BrowserContextType>;
99

10-
export function BrowserContextProvider(props: ParentProps) {
11-
return (
12-
<BrowserContext.Provider value={{}}>
13-
{props.children}
14-
</BrowserContext.Provider>
15-
);
16-
}
10+
// export function BrowserContextProvider(props: ParentProps) {
11+
// return (
12+
// <BrowserContext.Provider value={}>
13+
// {props.children}
14+
// </BrowserContext.Provider>
15+
// );
16+
// }
1717

18-
export default function useBrowserController() {
19-
return useContext(BrowserContext);
20-
}
18+
// export default function useBrowserController() {
19+
// return useContext(BrowserContext);
20+
// }

apps/desktop/src/ui/hooks/useCommand.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,7 @@ export default function useCommand<R, E, Args extends unknown[]>(
1010
cmd: (...args: Args) => Promise<Result<R, E>>,
1111
...args: Args
1212
): ResourceReturn<R> {
13-
return createResource(async () => {
14-
console.log('aaaa', cmd);
15-
const test = await tryResult(cmd, ...args);
16-
console.log('bbbb');
17-
return test;
18-
});
13+
return createResource(async () => await tryResult(cmd, ...args));
1914
}
2015

2116
export async function tryResult<R, E, Args extends unknown[]>(

apps/desktop/src/ui/pages/browser/BrowserMain.tsx

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { A } from '@solidjs/router';
22
import { Download01Icon, FileCode01Icon, FilterLinesIcon, SearchMdIcon } from '@untitled-theme/icons-solid';
3-
import { For, createSignal } from 'solid-js';
3+
import { For, createEffect, createSignal, onMount } from 'solid-js';
4+
import type { ManagedPackage } from '~bindings';
5+
import { bridge } from '~imports';
46
import Button from '~ui/components/base/Button';
57
import Dropdown from '~ui/components/base/Dropdown';
68
import TextField from '~ui/components/base/TextField';
79
import ModCard, { Provider } from '~ui/components/content/ModCard';
10+
import useCommand, { tryResult } from '~ui/hooks/useCommand';
811
import createSortable from '~utils/sorting';
912

1013
interface CardProps {
@@ -24,6 +27,36 @@ function BrowserMain() {
2427
provider: [Provider.Curseforge],
2528
});
2629

30+
const [modRowData, setModRowData] = createSignal<ModsRowProps[]>([]);
31+
32+
onMount(() => {
33+
Promise.all([
34+
tryResult(bridge.commands.randomMods),
35+
tryResult(bridge.commands.getMod, 'oneconfig'),
36+
tryResult(bridge.commands.getMod, 'chatting'),
37+
tryResult(bridge.commands.getMod, 'patcher'),
38+
]).then((res) => {
39+
const list: ModsRowProps[] = [
40+
{
41+
header: 'Polyfrost',
42+
category: 'polyfrost',
43+
packages: [
44+
res[1],
45+
res[2],
46+
res[3],
47+
],
48+
},
49+
{
50+
header: 'Random Mods',
51+
category: 'random',
52+
packages: res[0],
53+
},
54+
];
55+
56+
setModRowData(list);
57+
});
58+
});
59+
2760
const sortable = createSortable<CardProps>([], {
2861
'A-Z': (a, b) => a.name.localeCompare(b.name),
2962
'Z-A': (a, b) => b.name.localeCompare(a.name),
@@ -33,7 +66,7 @@ function BrowserMain() {
3366

3467
return (
3568
<div class="flex flex-col flex-1 h-full gap-2 relative">
36-
<div class="flex flex-row flex-1 justify-between sticky top-0 z-10 bg-primary">
69+
<div class="flex flex-row justify-between sticky top-0 z-10 bg-primary">
3770
<div class="flex flex-row gap-2 h-8">
3871

3972
<TextField
@@ -66,8 +99,8 @@ function BrowserMain() {
6699
</div>
67100
</div>
68101

69-
<div class="flex flex-col h-full flex-1 gap-4 py-2">
70-
<For each={_modRowData}>
102+
<div class="flex flex-col gap-4 py-2">
103+
<For each={modRowData()}>
71104
{row => (
72105
<ModsRow {...row} />
73106
)}
@@ -78,32 +111,10 @@ function BrowserMain() {
78111
);
79112
}
80113

81-
// export const modStore: Mod[] = [
82-
// {
83-
// id: '1yIQcc2b',
84-
// name: 'EvergreenHUD',
85-
// description: 'Improves your heads up display.',
86-
// author: 'Polyfrost',
87-
// icon_url: 'https://cdn.modrinth.com/data/1yIQcc2b/icon.png',
88-
// page_url: 'https://modrinth.com/mod/evergreenhud',
89-
// provider: Provider.Modrinth,
90-
// downloads: 281700,
91-
// ratings: 220,
92-
// },
93-
// ];
94-
95-
// const _modRowData: ModsRowProps[] = [
96-
// {
97-
// header: 'Highly Endorsed',
98-
// category: 'endorsed',
99-
// mods: modStore,
100-
// },
101-
// ];
102-
103114
interface ModsRowProps {
104115
header: string;
105116
category: string;
106-
mods: Mod[];
117+
packages: ManagedPackage[];
107118
};
108119

109120
function ModsRow(props: ModsRowProps) {
@@ -114,8 +125,8 @@ function ModsRow(props: ModsRowProps) {
114125
<A class="text-fg-secondary hover:text-fg-secondary-hover active:text-fg-secondary-pressed" href={`category?category=${props.category}`}>See all</A>
115126
</div>
116127

117-
<div class="flex flex-row gap-2">
118-
<For each={props.mods}>
128+
<div class="flex flex-row gap-2 max-w-full flex-wrap">
129+
<For each={props.packages}>
119130
{mod => <ModCard {...mod} />}
120131
</For>
121132
</div>

0 commit comments

Comments
 (0)