You've already forked AstralRinth
forked from didirus/AstralRinth
Starts adding search pages to launcher. (#49)
* launcher base gui initial * Bootstraps router, Omorphia, and prettier. * Adds pages. Adds Vuex. SideBar nav contains user section and pages section. * Adds Instance markup. Instances added to Home page. * Adds News to home page. * Adds settings to nav. Other touches. * Polishing initial base GUI. * Moves some styling to assets. Changes px values to rem. * Removes pointless border-radius CSS. * Implements Omorphia vars. * Adds trending mods section. * Updates home page. * Swaps Vuex implementation for Pinia. * Fixes invalid CSS on instance list item hover. * Adds @ path resolve for imports. * First pass on search page. * Fix some styling of row display * Cleaning up styles and markup. * Fixes overall layout issues. * Cleans up more styling. Modifies AppBar coloring. * Allows pagination arrows to conditionally appear in RowDisplay. * Adds paging behavior in RowDisplay. * Updates nav and settings button styling. * Brings in Knossos style for trending mods. Polishes News CSS. * Updates Omorphia. Starts addressing PR comments. * Addresses some more PR comments. * Changes side navigation styling. Active route class implemented. * Combines trending and popular row. * Makes images more realistic. Adds CTA to instances. * Converts all instances to card style. Converts more styles to rem. * Moves Navigation and UserSection into App.vue * Adds Modrinth favicon. * Cleans up branch after merge. * Removes unused styling. * Adds transition to news card. * Adds ofetch. Separates stores. More logic moved to instance store. Browse hits API. * Modifies Browse instance styling. Moves Browse results out of Instance.vue. * First pass on filtering. * Points search at prod API. * Updates Omorphia package. Adds index sorting. * Fills out search functionality. * Renames state files. Moves SearchPanel into Browse. Fixes checkbox styling. * Changes how facets are composed. Dynamically sets loaders and categories. * Moves search state to searchStore. Cleans up some code. * Ups h2 font-size. Wraps search panel in Card. * Cleans up branch after merge. Fixes some Browse styling. * Search store produces query string. API call made in Browse. * Changes filter-panel styling. * Uses client and server icons directly. Removes dead code from search store. * Clear button disabled on initial state. Accesses store directly, removes some dead code. Fixes search panel styling. * Generates proj tags in Browse. Removes getter in search store. * Removes unnecessary code. * Reworks facet management. Fixes some styling. * Relabels Tauri calls in tags.js. Attempts to call helper in Browse. * fixed win10 stack overflow * cargo fmt * Makes computed value. Gets tags from Tauri. Overrides Omorphia style. Fixes dropdown width. --------- Co-authored-by: Jai A <jaiagr+gpg@pm.me> Co-authored-by: CodexAdrian <83074853+CodexAdrian@users.noreply.github.com> Co-authored-by: Wyatt Verchere <wverchere@gmail.com>
This commit is contained in:
@@ -134,13 +134,12 @@ impl Tags {
|
||||
// Fetches the tags from the Modrinth API and stores them in the database
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub async fn fetch_update(&mut self) -> crate::Result<()> {
|
||||
let categories = self.fetch_tag::<Category>("category");
|
||||
let loaders = self.fetch_tag::<Loader>("loader");
|
||||
let game_versions = self.fetch_tag::<GameVersion>("game_version");
|
||||
let licenses = self.fetch_tag::<License>("license");
|
||||
let donation_platforms =
|
||||
self.fetch_tag::<DonationPlatform>("donation_platform");
|
||||
let report_types = self.fetch_tag::<String>("report_type");
|
||||
let categories = self.fetch_tag("category");
|
||||
let loaders = self.fetch_tag("loader");
|
||||
let game_versions = self.fetch_tag("game_version");
|
||||
let licenses = self.fetch_tag("license");
|
||||
let donation_platforms = self.fetch_tag("donation_platform");
|
||||
let report_types = self.fetch_tag("report_type");
|
||||
|
||||
let (
|
||||
categories,
|
||||
@@ -149,59 +148,60 @@ impl Tags {
|
||||
licenses,
|
||||
donation_platforms,
|
||||
report_types,
|
||||
) = futures::join!(
|
||||
) = tokio::try_join!(
|
||||
categories,
|
||||
loaders,
|
||||
game_versions,
|
||||
licenses,
|
||||
donation_platforms,
|
||||
report_types
|
||||
);
|
||||
)?;
|
||||
|
||||
// Store the tags in the database
|
||||
self.0.categories.insert(
|
||||
"categories",
|
||||
bincode::encode_to_vec(categories?, *BINCODE_CONFIG)?,
|
||||
bincode::encode_to_vec(categories.json().await?, *BINCODE_CONFIG)?,
|
||||
)?;
|
||||
self.0.loaders.insert(
|
||||
"loaders",
|
||||
bincode::encode_to_vec(loaders?, *BINCODE_CONFIG)?,
|
||||
bincode::encode_to_vec(loaders.json().await?, *BINCODE_CONFIG)?,
|
||||
)?;
|
||||
self.0.game_versions.insert(
|
||||
"game_versions",
|
||||
bincode::encode_to_vec(game_versions?, *BINCODE_CONFIG)?,
|
||||
bincode::encode_to_vec(
|
||||
game_versions.json().await?,
|
||||
*BINCODE_CONFIG,
|
||||
)?,
|
||||
)?;
|
||||
self.0.licenses.insert(
|
||||
"licenses",
|
||||
bincode::encode_to_vec(licenses?, *BINCODE_CONFIG)?,
|
||||
bincode::encode_to_vec(licenses.json().await?, *BINCODE_CONFIG)?,
|
||||
)?;
|
||||
self.0.donation_platforms.insert(
|
||||
"donation_platforms",
|
||||
bincode::encode_to_vec(donation_platforms?, *BINCODE_CONFIG)?,
|
||||
bincode::encode_to_vec(
|
||||
donation_platforms.json().await?,
|
||||
*BINCODE_CONFIG,
|
||||
)?,
|
||||
)?;
|
||||
self.0.report_types.insert(
|
||||
"report_types",
|
||||
bincode::encode_to_vec(report_types?, *BINCODE_CONFIG)?,
|
||||
bincode::encode_to_vec(
|
||||
report_types.json().await?,
|
||||
*BINCODE_CONFIG,
|
||||
)?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub async fn fetch_tag<T>(
|
||||
pub async fn fetch_tag(
|
||||
&self,
|
||||
tag_type: &str,
|
||||
) -> Result<Vec<T>, reqwest::Error>
|
||||
where
|
||||
T: serde::de::DeserializeOwned,
|
||||
{
|
||||
) -> Result<reqwest::Response, reqwest::Error> {
|
||||
let url = &format!("{MODRINTH_API_URL}tag/{}", tag_type);
|
||||
let content = REQWEST_CLIENT
|
||||
.get(url)
|
||||
.send()
|
||||
.await?
|
||||
.json::<Vec<T>>()
|
||||
.await?;
|
||||
let content = REQWEST_CLIENT.get(url).send().await?;
|
||||
Ok(content)
|
||||
}
|
||||
}
|
||||
|
||||
3
theseus_gui/.gitignore
vendored
3
theseus_gui/.gitignore
vendored
@@ -10,7 +10,6 @@ pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
@@ -24,3 +23,5 @@ dist-ssr
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
generated.js
|
||||
|
||||
@@ -7,6 +7,7 @@ node_modules
|
||||
.env
|
||||
dist
|
||||
*.md
|
||||
package.json
|
||||
|
||||
generated/
|
||||
!.gitkeep
|
||||
|
||||
4
theseus_gui/dist/.gitignore
vendored
Normal file
4
theseus_gui/dist/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# except the gitignore
|
||||
!.gitignore
|
||||
@@ -14,11 +14,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^1.2.0",
|
||||
"axios": "^1.3.4",
|
||||
"ofetch": "^1.0.1",
|
||||
"omorphia": "^0.4.2",
|
||||
"pinia": "^2.0.33",
|
||||
"vite-svg-loader": "^4.0.0",
|
||||
"vue": "^3.2.45",
|
||||
"vue-multiselect": "^3.0.0-alpha.2",
|
||||
"vue-router": "4"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -33,4 +34,4 @@
|
||||
"vite": "^4.0.0",
|
||||
"vite-plugin-eslint": "^1.8.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,19 +11,17 @@ import {
|
||||
SettingsIcon,
|
||||
Avatar,
|
||||
} from 'omorphia'
|
||||
import { useTheming, useInstances } from '@/store/state'
|
||||
import { useTheming } from '@/store/state'
|
||||
import { toggleTheme } from '@/helpers/theme'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const theme = useTheming()
|
||||
const instances = useInstances()
|
||||
instances.fetchInstances()
|
||||
const themeStore = useTheming()
|
||||
|
||||
toggleTheme(theme.darkTheme)
|
||||
toggleTheme(themeStore.darkTheme)
|
||||
|
||||
watch(theme, (newState) => {
|
||||
watch(themeStore, (newState) => {
|
||||
toggleTheme(newState.darkTheme)
|
||||
})
|
||||
</script>
|
||||
@@ -59,7 +57,9 @@ watch(theme, (newState) => {
|
||||
</section>
|
||||
</div>
|
||||
<div class="router-view">
|
||||
<RouterView />
|
||||
<Suspense>
|
||||
<RouterView />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -63,8 +63,8 @@ const handleRightPage = () => {
|
||||
<p>{{ props.label }}</p>
|
||||
<hr aria-hidden="true" />
|
||||
<div v-if="allowPagination" class="pagination">
|
||||
<ChevronLeftIcon @click="handleLeftPage" />
|
||||
<ChevronRightIcon @click="handleRightPage" />
|
||||
<ChevronLeftIcon role="button" @click="handleLeftPage" />
|
||||
<ChevronRightIcon role="button" @click="handleRightPage" />
|
||||
</div>
|
||||
</div>
|
||||
<section v-if="shouldRenderNormalInstances" ref="modsRow" class="instances">
|
||||
|
||||
@@ -12,17 +12,17 @@ export async function get_tag_bundle() {
|
||||
|
||||
// Gets cached category tags
|
||||
export async function get_categories() {
|
||||
return await invoke('tags_get_categories')
|
||||
return await invoke('tags_get_category_tags')
|
||||
}
|
||||
|
||||
// Gets cached loaders tags
|
||||
export async function get_loaders() {
|
||||
return await invoke('tags_get_loaders')
|
||||
return await invoke('tags_get_loader_tags')
|
||||
}
|
||||
|
||||
// Gets cached game_versions tags
|
||||
export async function get_game_versions() {
|
||||
return await invoke('tags_get_game_versions')
|
||||
return await invoke('tags_get_game_version_tags')
|
||||
}
|
||||
|
||||
// Gets cached licenses tags
|
||||
|
||||
@@ -1,7 +1,536 @@
|
||||
<script setup></script>
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { ofetch } from 'ofetch'
|
||||
import {
|
||||
Pagination,
|
||||
ProjectCard,
|
||||
Checkbox,
|
||||
Button,
|
||||
ClearIcon,
|
||||
SearchIcon,
|
||||
DropdownSelect,
|
||||
SearchFilter,
|
||||
Card,
|
||||
ClientIcon,
|
||||
ServerIcon,
|
||||
} from 'omorphia'
|
||||
import Multiselect from 'vue-multiselect'
|
||||
import { useSearch } from '@/store/state'
|
||||
import { get_categories, get_loaders, get_game_versions } from '@/helpers/tags'
|
||||
|
||||
// Pull search store
|
||||
const searchStore = useSearch()
|
||||
|
||||
const selectedVersions = ref([])
|
||||
const showSnapshots = ref(false)
|
||||
|
||||
// Sets the clear button's disabled attr
|
||||
const isClearDisabled = computed({
|
||||
get() {
|
||||
if (searchStore.facets.length > 0) return false
|
||||
if (searchStore.orFacets.length > 0) return false
|
||||
|
||||
if (searchStore.environments.server === true || searchStore.environments.client === true)
|
||||
return false
|
||||
if (searchStore.openSource === true) return false
|
||||
if (selectedVersions.value.length > 0) return false
|
||||
return true
|
||||
},
|
||||
})
|
||||
|
||||
const categories = await get_categories()
|
||||
const loaders = await get_loaders()
|
||||
const availableGameVersions = await get_game_versions()
|
||||
|
||||
/**
|
||||
* Adds or removes facets from state
|
||||
* @param {String} facet The facet to commit to state
|
||||
*/
|
||||
const toggleFacet = async (facet) => {
|
||||
const index = searchStore.facets.indexOf(facet)
|
||||
|
||||
if (index !== -1) searchStore.facets.splice(index, 1)
|
||||
else searchStore.facets.push(facet)
|
||||
|
||||
await getSearchResults()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or removes orFacets from state
|
||||
* @param {String} orFacet The orFacet to commit to state
|
||||
*/
|
||||
const toggleOrFacet = async (orFacet) => {
|
||||
const index = searchStore.orFacets.indexOf(orFacet)
|
||||
|
||||
if (index !== -1) searchStore.orFacets.splice(index, 1)
|
||||
else searchStore.orFacets.push(orFacet)
|
||||
|
||||
await getSearchResults()
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the API request to labrinth
|
||||
*/
|
||||
const getSearchResults = async () => {
|
||||
const queryString = searchStore.getQueryString()
|
||||
const response = await ofetch(`https://api.modrinth.com/v2/search${queryString}`)
|
||||
|
||||
searchStore.setSearchResults(response)
|
||||
}
|
||||
await getSearchResults()
|
||||
|
||||
/**
|
||||
* For when user enters input in search bar
|
||||
*/
|
||||
const refreshSearch = async () => {
|
||||
await getSearchResults()
|
||||
}
|
||||
|
||||
/**
|
||||
* For when the user changes the Sort dropdown
|
||||
* @param {Object} e Event param to see selected option
|
||||
*/
|
||||
const handleSort = async (e) => {
|
||||
searchStore.filter = e.option
|
||||
await getSearchResults()
|
||||
}
|
||||
|
||||
/**
|
||||
* For when user changes Limit dropdown
|
||||
* @param {Object} e Event param to see selected option
|
||||
*/
|
||||
const handleLimit = async (e) => {
|
||||
searchStore.limit = e.option
|
||||
await getSearchResults()
|
||||
}
|
||||
|
||||
/**
|
||||
* For when user pages results
|
||||
* @param {Number} page The new page to display
|
||||
*/
|
||||
const switchPage = async (page) => {
|
||||
searchStore.currentPage = parseInt(page)
|
||||
if (page === 1) searchStore.offset = 0
|
||||
else searchStore.offset = searchStore.currentPage * 10 - 10
|
||||
await getSearchResults()
|
||||
}
|
||||
|
||||
/**
|
||||
* For when a user interacts with version filters
|
||||
*/
|
||||
const handleVersionSelect = async () => {
|
||||
searchStore.activeVersions = selectedVersions.value.map((ver) => ver)
|
||||
await getSearchResults()
|
||||
}
|
||||
|
||||
/**
|
||||
* For when user resets all filters
|
||||
*/
|
||||
const handleReset = async () => {
|
||||
searchStore.resetFilters()
|
||||
selectedVersions.value = []
|
||||
isClearDisabled.value = true
|
||||
await getSearchResults()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p>Browse page</p>
|
||||
<div class="search-container">
|
||||
<aside class="filter-panel">
|
||||
<Button role="button" :disabled="isClearDisabled" @click="handleReset"
|
||||
><ClearIcon />Clear Filters</Button
|
||||
>
|
||||
<div class="categories">
|
||||
<h2>Categories</h2>
|
||||
<div
|
||||
v-for="category in categories.filter((cat) => cat.project_type === 'modpack')"
|
||||
:key="category.name"
|
||||
>
|
||||
<SearchFilter
|
||||
:active-filters="searchStore.facets"
|
||||
:icon="category.icon"
|
||||
:display-name="category.name"
|
||||
:facet-name="`categories:${encodeURIComponent(category.name)}`"
|
||||
class="filter-checkbox"
|
||||
@toggle="toggleFacet"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="loaders">
|
||||
<h2>Loaders</h2>
|
||||
<div
|
||||
v-for="loader in loaders.filter((l) => l.supported_project_types?.includes('modpack'))"
|
||||
:key="loader"
|
||||
>
|
||||
<SearchFilter
|
||||
:active-filters="searchStore.orFacets"
|
||||
:icon="loader.icon"
|
||||
:display-name="loader.name"
|
||||
:facet-name="`categories:${encodeURIComponent(loader.name)}`"
|
||||
class="filter-checkbox"
|
||||
@toggle="toggleOrFacet"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="environment">
|
||||
<h2>Environments</h2>
|
||||
<SearchFilter
|
||||
v-model="searchStore.environments.client"
|
||||
display-name="Client"
|
||||
:facet-name="client"
|
||||
class="filter-checkbox"
|
||||
@click="refreshSearch"
|
||||
>
|
||||
<ClientIcon aria-hidden="true" />
|
||||
</SearchFilter>
|
||||
<SearchFilter
|
||||
v-model="searchStore.environments.server"
|
||||
display-name="Server"
|
||||
:facet-name="server"
|
||||
class="filter-checkbox"
|
||||
@click="refreshSearch"
|
||||
>
|
||||
<ServerIcon aria-hidden="true" />
|
||||
</SearchFilter>
|
||||
</div>
|
||||
<div class="versions">
|
||||
<h2>Minecraft versions</h2>
|
||||
<Checkbox v-model="showSnapshots" class="filter-checkbox">Show snapshots</Checkbox>
|
||||
<multiselect
|
||||
v-model="selectedVersions"
|
||||
:options="
|
||||
showSnapshots
|
||||
? availableGameVersions.map((x) => x.version)
|
||||
: availableGameVersions
|
||||
.filter((it) => it.version_type === 'release')
|
||||
.map((x) => x.version)
|
||||
"
|
||||
:multiple="true"
|
||||
:searchable="true"
|
||||
:show-no-results="false"
|
||||
:close-on-select="false"
|
||||
:clear-search-on-select="false"
|
||||
:show-labels="false"
|
||||
:selectable="() => selectedVersions.length <= 6"
|
||||
placeholder="Choose versions..."
|
||||
@update:model-value="handleVersionSelect"
|
||||
/>
|
||||
</div>
|
||||
<div class="open-source">
|
||||
<h2>Open source</h2>
|
||||
<Checkbox v-model="searchStore.openSource" class="filter-checkbox" @click="refreshSearch">
|
||||
Open source
|
||||
</Checkbox>
|
||||
</div>
|
||||
</aside>
|
||||
<div class="search">
|
||||
<Card class="search-panel-container">
|
||||
<div class="search-panel">
|
||||
<div class="iconified-input">
|
||||
<SearchIcon aria-hidden="true" />
|
||||
<input
|
||||
v-model="searchStore.searchInput"
|
||||
type="text"
|
||||
placeholder="Search.."
|
||||
@input="refreshSearch"
|
||||
/>
|
||||
</div>
|
||||
<span>Sort by</span>
|
||||
<DropdownSelect
|
||||
name="Sort dropdown"
|
||||
:options="[
|
||||
'Relevance',
|
||||
'Download count',
|
||||
'Follow count',
|
||||
'Recently published',
|
||||
'Recently updated',
|
||||
]"
|
||||
:default-value="searchStore.filter"
|
||||
:model-value="searchStore.filter"
|
||||
class="sort-dropdown"
|
||||
@change="handleSort"
|
||||
/>
|
||||
<span>Show per page</span>
|
||||
<DropdownSelect
|
||||
name="Limit dropdown"
|
||||
:options="['5', '10', '15', '20', '50', '100']"
|
||||
:default-value="searchStore.limit.toString()"
|
||||
:model-value="searchStore.limit.toString()"
|
||||
class="limit-dropdown"
|
||||
@change="handleLimit"
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
<Pagination
|
||||
:page="searchStore.currentPage"
|
||||
:count="searchStore.pageCount"
|
||||
@switch-page="switchPage"
|
||||
/>
|
||||
<section class="project-list display-mode--list instance-results" role="list">
|
||||
<ProjectCard
|
||||
v-for="result in searchStore.searchResults"
|
||||
:id="result?.project_id"
|
||||
:key="result?.project_id"
|
||||
class="result-project-item"
|
||||
:type="result?.project_type"
|
||||
:name="result?.title"
|
||||
:description="result?.description"
|
||||
:icon-url="result?.icon_url"
|
||||
:downloads="result?.downloads?.toString()"
|
||||
:follows="result?.follows?.toString()"
|
||||
:created-at="result?.date_created"
|
||||
:updated-at="result?.date_modified"
|
||||
:categories="[
|
||||
...categories.filter(
|
||||
(cat) =>
|
||||
result?.display_categories.includes(cat.name) && cat.project_type === 'modpack'
|
||||
),
|
||||
...loaders.filter(
|
||||
(loader) =>
|
||||
result?.display_categories.includes(loader.name) &&
|
||||
loader.supported_project_types?.includes('modpack')
|
||||
),
|
||||
]"
|
||||
:project-type-display="result?.project_type"
|
||||
project-type-url="instance"
|
||||
:server-side="result?.server_side"
|
||||
:client-side="result?.client_side"
|
||||
:show-updated-date="false"
|
||||
:color="result?.color"
|
||||
>
|
||||
</ProjectCard>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
|
||||
<style lang="scss">
|
||||
.search-panel-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-top: 1rem;
|
||||
padding: 0.8rem !important;
|
||||
|
||||
.search-panel {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
width: 100%;
|
||||
gap: 1rem;
|
||||
margin: 1rem auto;
|
||||
white-space: nowrap;
|
||||
|
||||
.sort-dropdown {
|
||||
min-width: 12.18rem;
|
||||
}
|
||||
|
||||
.limit-dropdown {
|
||||
width: 5rem;
|
||||
}
|
||||
|
||||
.iconified-input {
|
||||
width: 75%;
|
||||
|
||||
input {
|
||||
flex-basis: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-panel {
|
||||
button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
|
||||
svg {
|
||||
margin-right: 0.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
|
||||
.filter-panel {
|
||||
position: fixed;
|
||||
width: 16rem;
|
||||
background: var(--color-raised-bg);
|
||||
padding: 1rem 1rem 3rem 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
height: fit-content;
|
||||
max-height: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
h2 {
|
||||
color: var(--color-contrast);
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 1.16rem;
|
||||
}
|
||||
|
||||
.filter-checkbox {
|
||||
margin-bottom: 0.3rem;
|
||||
font-size: 1rem;
|
||||
text-transform: capitalize;
|
||||
|
||||
svg {
|
||||
display: flex;
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
button.checkbox {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
margin: 0 1rem 0 17rem;
|
||||
width: 100%;
|
||||
|
||||
.instance-project-item {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.result-project-item {
|
||||
a {
|
||||
&:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.multiselect {
|
||||
color: var(--color-base) !important;
|
||||
outline: 2px solid transparent;
|
||||
|
||||
.multiselect__input:focus-visible {
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
padding: 0 !important;
|
||||
min-height: 0 !important;
|
||||
font-weight: normal !important;
|
||||
margin-left: 0.5rem;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
input {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
border: none !important;
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
input::placeholder {
|
||||
color: var(--color-base);
|
||||
}
|
||||
|
||||
.multiselect__tags {
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--color-button-bg);
|
||||
box-shadow: var(--shadow-inset-sm);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding-left: 0.5rem;
|
||||
font-size: 1rem;
|
||||
|
||||
transition: background-color 0.1s ease-in-out;
|
||||
|
||||
&:active {
|
||||
filter: brightness(1.25);
|
||||
|
||||
.multiselect__spinner {
|
||||
filter: brightness(1.25);
|
||||
}
|
||||
}
|
||||
|
||||
.multiselect__single {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.multiselect__tag {
|
||||
border-radius: var(--radius-md);
|
||||
color: var(--color-base);
|
||||
background: transparent;
|
||||
border: 2px solid var(--color-brand);
|
||||
}
|
||||
|
||||
.multiselect__tag-icon {
|
||||
background: transparent;
|
||||
|
||||
&:after {
|
||||
color: var(--color-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
.multiselect__placeholder {
|
||||
color: var(--color-base);
|
||||
margin-left: 0.5rem;
|
||||
opacity: 0.6;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.multiselect__content-wrapper {
|
||||
background: var(--color-button-bg);
|
||||
border: none;
|
||||
overflow-x: hidden;
|
||||
box-shadow: var(--shadow-inset-sm), var(--shadow-floating);
|
||||
width: 100%;
|
||||
|
||||
.multiselect__element {
|
||||
.multiselect__option--highlight {
|
||||
background: var(--color-button-bg);
|
||||
filter: brightness(1.25);
|
||||
color: var(--color-contrast);
|
||||
}
|
||||
|
||||
.multiselect__option--selected {
|
||||
background: var(--color-brand);
|
||||
font-weight: bold;
|
||||
color: var(--color-accent-contrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.multiselect__spinner {
|
||||
background: var(--color-button-bg);
|
||||
|
||||
&:active {
|
||||
filter: brightness(1.25);
|
||||
}
|
||||
}
|
||||
|
||||
&.multiselect--disabled {
|
||||
background: none;
|
||||
|
||||
.multiselect__current,
|
||||
.multiselect__select {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.multiselect--above .multiselect__content-wrapper {
|
||||
border-top: none !important;
|
||||
border-top-left-radius: var(--radius-md) !important;
|
||||
border-top-right-radius: var(--radius-md) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
import { useInstances, useNews } from '@/store/state'
|
||||
import RowDisplay from '@/components/RowDisplay.vue'
|
||||
|
||||
const instances = useInstances()
|
||||
const news = useNews()
|
||||
instances.fetchInstances()
|
||||
news.fetchNews()
|
||||
const instanceStore = useInstances()
|
||||
const newsStore = useNews()
|
||||
instanceStore.fetchInstances()
|
||||
newsStore.fetchNews()
|
||||
|
||||
// Remove once state is populated with real data
|
||||
const recentInstances = instances.instances.slice(0, 4)
|
||||
const popularInstances = instances.instances.filter((i) => i.downloads > 50 || i.trending)
|
||||
const recentInstances = instanceStore.instances.slice(0, 4)
|
||||
const popularInstances = instanceStore.instances.filter((i) => i.downloads > 50 || i.trending)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<RowDisplay label="Jump back in" :instances="recentInstances" :can-paginate="false" />
|
||||
<RowDisplay label="Popular packs" :instances="popularInstances" :can-paginate="true" />
|
||||
<RowDisplay label="News & updates" :news="news.news" :can-paginate="true" />
|
||||
<RowDisplay label="News & updates" :news="newsStore.news" :can-paginate="true" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<div class="instance-container">
|
||||
<div class="side-cards">
|
||||
<Card class="instance-card">
|
||||
<Avatar size="lg" :src="getInstance(instances).img" />
|
||||
<Avatar size="lg" :src="getInstance(instanceStore).img" />
|
||||
<div class="instance-info">
|
||||
<h2 class="name">{{ getInstance(instances).name }}</h2>
|
||||
Fabric {{ getInstance(instances).version }}
|
||||
<h2 class="name">{{ getInstance(instanceStore).name }}</h2>
|
||||
Fabric {{ getInstance(instanceStore).version }}
|
||||
</div>
|
||||
<span class="button-group">
|
||||
<Button color="primary" class="instance-button">
|
||||
@@ -43,14 +43,14 @@ import { BoxIcon, SettingsIcon, FileIcon, Button, Avatar, Card, Promotion } from
|
||||
import { PlayIcon, OpenFolderIcon } from '@/assets/icons'
|
||||
import { useInstances } from '@/store/state'
|
||||
|
||||
const instances = useInstances()
|
||||
instances.fetchInstances()
|
||||
const instanceStore = useInstances()
|
||||
instanceStore.fetchInstances()
|
||||
</script>
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
getInstance(instances) {
|
||||
return instances.instances.find((i) => i.id === parseInt(this.$route.params.id))
|
||||
getInstance(instanceStore) {
|
||||
return instanceStore.instances.find((i) => i.id === parseInt(this.$route.params.id))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
115
theseus_gui/src/store/instances.js
Normal file
115
theseus_gui/src/store/instances.js
Normal file
@@ -0,0 +1,115 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useInstances = defineStore('instanceStore', {
|
||||
state: () => ({
|
||||
instances: [],
|
||||
}),
|
||||
actions: {
|
||||
fetchInstances() {
|
||||
// Fetch from Tauri backend. We will repurpose this to get current instances, news, and popular packs. This action is distinct from the search action
|
||||
const instances = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Fabulously Optimized',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.18.1',
|
||||
downloads: 10,
|
||||
trending: true,
|
||||
img: 'https://cdn.modrinth.com/user/MpxzqsyW/eb0038489a55e7e7a188a5b50462f0b10dfc1613.jpeg',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'New Caves',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.18 ',
|
||||
downloads: 8,
|
||||
trending: true,
|
||||
img: 'https://cdn.modrinth.com/data/ssUbhMkL/icon.png',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'All the Mods 6',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.16.5',
|
||||
downloads: 4,
|
||||
trending: true,
|
||||
img: 'https://avatars1.githubusercontent.com/u/6166773?v=4',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Bees',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/data/ssUbhMkL/icon.png',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'SkyFactory 4',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.12.2',
|
||||
downloads: 1000,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/user/MpxzqsyW/eb0038489a55e7e7a188a5b50462f0b10dfc1613.jpeg',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'RLCraft',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.12.2',
|
||||
downloads: 10000,
|
||||
trending: false,
|
||||
img: 'https://avatars1.githubusercontent.com/u/6166773?v=4',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Regrowth',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.7.10',
|
||||
downloads: 1000,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/data/ssUbhMkL/icon.png',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'Birds',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://avatars.githubusercontent.com/u/83074853?v=4',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: 'Dogs',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/user/MpxzqsyW/eb0038489a55e7e7a188a5b50462f0b10dfc1613.jpeg',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: 'Cats',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/data/ssUbhMkL/icon.png',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: 'Rabbits',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://avatars1.githubusercontent.com/u/6166773?v=4',
|
||||
},
|
||||
]
|
||||
|
||||
this.instances = [...instances]
|
||||
},
|
||||
},
|
||||
})
|
||||
35
theseus_gui/src/store/news.js
Normal file
35
theseus_gui/src/store/news.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useNews = defineStore('newsStore', {
|
||||
state: () => ({ news: [] }),
|
||||
actions: {
|
||||
fetchNews() {
|
||||
// Fetch from backend.
|
||||
const news = [
|
||||
{
|
||||
id: 1,
|
||||
headline: 'Caves & Cliffs Update: Part II Dev Q&A',
|
||||
blurb: 'Your questions, answered!',
|
||||
source: 'From Minecraft.Net',
|
||||
img: 'https://avatars1.githubusercontent.com/u/6166773?v=4',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
headline: 'Project of the WeeK: Gobblygook',
|
||||
blurb: 'Your questions, answered!',
|
||||
source: 'Modrinth Blog',
|
||||
img: 'https://avatars.githubusercontent.com/t/3923733?s=280&v=4',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
headline: 'Oreo makes a launcher',
|
||||
blurb: 'What did it take?',
|
||||
source: 'Modrinth Blog',
|
||||
img: 'https://avatars.githubusercontent.com/u/30800863?v=4',
|
||||
},
|
||||
]
|
||||
|
||||
this.news = [...news]
|
||||
},
|
||||
},
|
||||
})
|
||||
116
theseus_gui/src/store/search.js
Normal file
116
theseus_gui/src/store/search.js
Normal file
@@ -0,0 +1,116 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useSearch = defineStore('searchStore', {
|
||||
state: () => ({
|
||||
searchResults: [],
|
||||
searchInput: '',
|
||||
totalHits: 0,
|
||||
currentPage: 1,
|
||||
pageCount: 1,
|
||||
offset: 0,
|
||||
filter: 'Relevance',
|
||||
facets: [],
|
||||
orFacets: [],
|
||||
environments: {
|
||||
client: false,
|
||||
server: false,
|
||||
},
|
||||
activeVersions: [],
|
||||
openSource: false,
|
||||
limit: 20,
|
||||
}),
|
||||
actions: {
|
||||
getQueryString() {
|
||||
let andFacets = ['project_type:modpack']
|
||||
|
||||
// Iterate through possible andFacets
|
||||
this.facets.forEach((facet) => {
|
||||
andFacets.push(facet)
|
||||
})
|
||||
// Add open source to andFacets if enabled
|
||||
if (this.openSource) andFacets.push('open_source:true')
|
||||
|
||||
// Create andFacet string
|
||||
let formattedAndFacets = ''
|
||||
andFacets.forEach((f) => (formattedAndFacets += `["${f}"],`))
|
||||
formattedAndFacets = formattedAndFacets.slice(0, formattedAndFacets.length - 1)
|
||||
formattedAndFacets += ''
|
||||
|
||||
// If orFacets are present, start building formatted orFacet filter
|
||||
let formattedOrFacets = ''
|
||||
if (this.orFacets.length > 0 || this.activeVersions.length > 0) {
|
||||
formattedOrFacets += '['
|
||||
// Aggregate normal orFacets
|
||||
this.orFacets.forEach((orF) => (formattedOrFacets += `"${orF}",`))
|
||||
|
||||
// Add version list to orFacets
|
||||
if (this.activeVersions.length > 0)
|
||||
this.activeVersions.forEach((ver) => (formattedOrFacets += `"versions:${ver}",`))
|
||||
|
||||
// Add environments to orFacets if enabled
|
||||
if (this.environments.client)
|
||||
formattedOrFacets += '"client_side:optional","client_side:required,"'
|
||||
if (this.environments.server)
|
||||
formattedOrFacets += '"server_side:optional","server_side:required,"'
|
||||
|
||||
formattedOrFacets = formattedOrFacets.slice(0, formattedOrFacets.length - 1)
|
||||
formattedOrFacets += ']'
|
||||
}
|
||||
|
||||
// Aggregate facet query string
|
||||
const facets = `&facets=[${formattedAndFacets}${
|
||||
formattedOrFacets.length > 0 ? `,${formattedOrFacets}` : ''
|
||||
}]`
|
||||
|
||||
// Configure results sorting
|
||||
let indexSort
|
||||
switch (this.filter) {
|
||||
case 'Download count':
|
||||
indexSort = 'downloads'
|
||||
break
|
||||
case 'Follow count':
|
||||
indexSort = 'follows'
|
||||
break
|
||||
case 'Recently published':
|
||||
indexSort = 'newest'
|
||||
break
|
||||
case 'Recently updated':
|
||||
indexSort = 'updated'
|
||||
break
|
||||
default:
|
||||
indexSort = 'relevance'
|
||||
}
|
||||
|
||||
return `?query=${this.searchInput || ''}&limit=${this.limit}&offset=${this.offset || 0}${
|
||||
facets || ''
|
||||
}&index=${indexSort}`
|
||||
},
|
||||
setSearchResults(response) {
|
||||
this.searchResults = [...response.hits]
|
||||
this.totalHits = response.total_hits
|
||||
this.offset = response.offset
|
||||
this.pageCount = Math.ceil(this.totalHits / this.limit)
|
||||
},
|
||||
toggleCategory(cat) {
|
||||
this.categories[cat] = !this.categories[cat]
|
||||
},
|
||||
toggleLoader(loader) {
|
||||
this.loaders[loader] = !this.loaders[loader]
|
||||
},
|
||||
toggleEnv(env) {
|
||||
this.environments[env] = !this.environments[env]
|
||||
},
|
||||
setVersions(versions) {
|
||||
this.activeVersions = versions
|
||||
},
|
||||
resetFilters() {
|
||||
this.facets = []
|
||||
this.orFacets = []
|
||||
Object.keys(this.environments).forEach((env) => {
|
||||
this.environments[env] = false
|
||||
})
|
||||
this.activeVersions = []
|
||||
this.openSource = false
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -1,156 +1,6 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { useInstances } from './instances'
|
||||
import { useSearch } from './search'
|
||||
import { useTheming } from './theme'
|
||||
import { useNews } from './news'
|
||||
|
||||
export const useTheming = defineStore('theme', {
|
||||
state: () => ({ darkTheme: true }),
|
||||
actions: {
|
||||
toggleTheme() {
|
||||
this.darkTheme = !this.darkTheme
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const useInstances = defineStore('instances', {
|
||||
state: () => ({ instances: [] }),
|
||||
actions: {
|
||||
fetchInstances() {
|
||||
// Fetch from backend.
|
||||
const instances = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Fabulously Optimized',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.18.1',
|
||||
downloads: 10,
|
||||
trending: true,
|
||||
img: 'https://cdn.modrinth.com/user/MpxzqsyW/eb0038489a55e7e7a188a5b50462f0b10dfc1613.jpeg',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'New Caves',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.18 ',
|
||||
downloads: 8,
|
||||
trending: true,
|
||||
img: 'https://cdn.modrinth.com/data/ssUbhMkL/icon.png',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'All the Mods 6',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.16.5',
|
||||
downloads: 4,
|
||||
trending: true,
|
||||
img: 'https://avatars1.githubusercontent.com/u/6166773?v=4',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Bees',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/data/ssUbhMkL/icon.png',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'SkyFactory 4',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.12.2',
|
||||
downloads: 1000,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/user/MpxzqsyW/eb0038489a55e7e7a188a5b50462f0b10dfc1613.jpeg',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'RLCraft',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.12.2',
|
||||
downloads: 10000,
|
||||
trending: false,
|
||||
img: 'https://avatars1.githubusercontent.com/u/6166773?v=4',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'Regrowth',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.7.10',
|
||||
downloads: 1000,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/data/ssUbhMkL/icon.png',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'Birds',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://avatars.githubusercontent.com/u/83074853?v=4',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: 'Dogs',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/user/MpxzqsyW/eb0038489a55e7e7a188a5b50462f0b10dfc1613.jpeg',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: 'Cats',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://cdn.modrinth.com/data/ssUbhMkL/icon.png',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: 'Rabbits',
|
||||
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit',
|
||||
version: '1.15.2',
|
||||
downloads: 9,
|
||||
trending: false,
|
||||
img: 'https://avatars1.githubusercontent.com/u/6166773?v=4',
|
||||
},
|
||||
]
|
||||
|
||||
this.instances = [...instances]
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const useNews = defineStore('news', {
|
||||
state: () => ({ news: [] }),
|
||||
actions: {
|
||||
fetchNews() {
|
||||
// Fetch from backend.
|
||||
const news = [
|
||||
{
|
||||
id: 1,
|
||||
headline: 'Caves & Cliffs Update: Part II Dev Q&A',
|
||||
blurb: 'Your questions, answered!',
|
||||
source: 'From Minecraft.Net',
|
||||
img: 'https://avatars1.githubusercontent.com/u/6166773?v=4',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
headline: 'Project of the WeeK: Gobblygook',
|
||||
blurb: 'Your questions, answered!',
|
||||
source: 'Modrinth Blog',
|
||||
img: 'https://avatars.githubusercontent.com/t/3923733?s=280&v=4',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
headline: 'Oreo makes a launcher',
|
||||
blurb: 'What did it take?',
|
||||
source: 'Modrinth Blog',
|
||||
img: 'https://avatars.githubusercontent.com/u/30800863?v=4',
|
||||
},
|
||||
]
|
||||
|
||||
this.news = [...news]
|
||||
},
|
||||
},
|
||||
})
|
||||
export { useInstances, useSearch, useTheming, useNews }
|
||||
|
||||
10
theseus_gui/src/store/theme.js
Normal file
10
theseus_gui/src/store/theme.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useTheming = defineStore('themeStore', {
|
||||
state: () => ({ darkTheme: true }),
|
||||
actions: {
|
||||
toggleTheme() {
|
||||
this.darkTheme = !this.darkTheme
|
||||
},
|
||||
},
|
||||
})
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
|
||||
"@babel/parser@^7.16.4":
|
||||
version "7.21.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.3.tgz#1d285d67a19162ff9daa358d4cb41d50c06220b3"
|
||||
integrity sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==
|
||||
version "7.21.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.4.tgz#94003fdfc520bbe2875d4ae557b43ddb6d880f17"
|
||||
integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==
|
||||
|
||||
"@esbuild/android-arm64@0.17.14":
|
||||
version "0.17.14"
|
||||
@@ -287,9 +287,9 @@
|
||||
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
|
||||
|
||||
"@types/eslint@^8.4.5":
|
||||
version "8.21.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.3.tgz#5794b3911f0f19e34e3a272c49cbdf48d6f543f2"
|
||||
integrity sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==
|
||||
version "8.37.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.37.0.tgz#29cebc6c2a3ac7fea7113207bf5a828fdf4d7ef1"
|
||||
integrity sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==
|
||||
dependencies:
|
||||
"@types/estree" "*"
|
||||
"@types/json-schema" "*"
|
||||
@@ -449,20 +449,6 @@ argparse@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||
|
||||
axios@^1.3.4:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024"
|
||||
integrity sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==
|
||||
dependencies:
|
||||
follow-redirects "^1.15.0"
|
||||
form-data "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
@@ -533,13 +519,6 @@ color-name@~1.1.4:
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
combined-stream@^1.0.8:
|
||||
version "1.0.8"
|
||||
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.20.3:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
@@ -635,10 +614,10 @@ deep-is@^0.1.3:
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
|
||||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
||||
|
||||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||
destr@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/destr/-/destr-1.2.2.tgz#7ba9befcafb645a50e76b260449c63927b51e22f"
|
||||
integrity sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA==
|
||||
|
||||
doctrine@^3.0.0:
|
||||
version "3.0.0"
|
||||
@@ -900,20 +879,6 @@ floating-vue@^2.0.0-beta.20:
|
||||
"@floating-ui/dom" "^0.1.10"
|
||||
vue-resize "^2.0.0-alpha.1"
|
||||
|
||||
follow-redirects@^1.15.0:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
@@ -1155,18 +1120,6 @@ mdurl@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
|
||||
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
mime-types@^2.1.12:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
@@ -1189,6 +1142,11 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
node-fetch-native@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.0.2.tgz#de3651399fda89a1a7c0bf6e7c4e9c239e8d0697"
|
||||
integrity sha512-KIkvH1jl6b3O7es/0ShyCgWLcfXxlBrLBbP3rOr23WArC66IMcU4DeZEeYEOwnopYhawLTn7/y+YtmASe8DFVQ==
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
@@ -1201,10 +1159,19 @@ nth-check@^2.0.1:
|
||||
dependencies:
|
||||
boolbase "^1.0.0"
|
||||
|
||||
ofetch@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.0.1.tgz#68b410d4494e37fa67b99e9a60172ae447b2c44c"
|
||||
integrity sha512-icBz2JYfEpt+wZz1FRoGcrMigjNKjzvufE26m9+yUiacRQRHwnNlGRPiDnW4op7WX/MR6aniwS8xw8jyVelF2g==
|
||||
dependencies:
|
||||
destr "^1.2.2"
|
||||
node-fetch-native "^1.0.2"
|
||||
ufo "^1.1.0"
|
||||
|
||||
omorphia@^0.4.2:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/omorphia/-/omorphia-0.4.2.tgz#0199e5a3ac2929da2307a7e81a4f1a4468eaf2eb"
|
||||
integrity sha512-bRKpLCIOGnqTPfeh4Ilz01rd+KYkO7qJY8Pi81t5Y4+//rX7FItLnMkmG3zifgoLCzi7aqsfsByhQptpm4/3kw==
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/omorphia/-/omorphia-0.4.3.tgz#a247e2e15b77b4b5f55fe766f1c64419bb6fbc72"
|
||||
integrity sha512-aGjtYhUrWNgjKM3HiL+MF5DdXfrllfDxql2mzu7JRzpjTB20xnksHKvU71x17FS9P1QXxumzADVF5v2rn9lb6A==
|
||||
dependencies:
|
||||
dayjs "^1.11.7"
|
||||
floating-vue "^2.0.0-beta.20"
|
||||
@@ -1320,11 +1287,6 @@ prettier@^2.8.7:
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450"
|
||||
integrity sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
||||
@@ -1502,6 +1464,11 @@ uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||
|
||||
ufo@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.1.1.tgz#e70265e7152f3aba425bd013d150b2cdf4056d7c"
|
||||
integrity sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||
@@ -1549,9 +1516,9 @@ vue-demi@*:
|
||||
integrity sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==
|
||||
|
||||
vue-eslint-parser@^9.0.1:
|
||||
version "9.1.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.1.0.tgz#0e121d1bb29bd10763c83e3cc583ee03434a9dd5"
|
||||
integrity sha512-NGn/iQy8/Wb7RrRa4aRkokyCZfOUWk19OP5HP6JEozQFX5AoS/t+Z0ZN7FY4LlmWc4FNI922V7cvX28zctN8dQ==
|
||||
version "9.1.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.1.1.tgz#3f4859be7e9bb7edaa1dc7edb05abffee72bf3dd"
|
||||
integrity sha512-C2aI/r85Q6tYcz4dpgvrs4wH/MqVrRAVIdpYedrxnATDHHkb+TroeRcDpKWGZCx/OcECMWfz7tVwQ8e+Opy6rA==
|
||||
dependencies:
|
||||
debug "^4.3.4"
|
||||
eslint-scope "^7.1.1"
|
||||
@@ -1561,6 +1528,11 @@ vue-eslint-parser@^9.0.1:
|
||||
lodash "^4.17.21"
|
||||
semver "^7.3.6"
|
||||
|
||||
vue-multiselect@^3.0.0-alpha.2:
|
||||
version "3.0.0-beta.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-multiselect/-/vue-multiselect-3.0.0-beta.1.tgz#f5c33677237fa9af0105f94783c3175330731e5a"
|
||||
integrity sha512-V+jpydtjyHcQ+yjHsEWEBrDAopOx/pufNkSAXNVDAGQ+ESDEJ7wYejNd9H1RiCnFOYK4yf1XSGqE+Mp3HJXmdg==
|
||||
|
||||
vue-resize@^2.0.0-alpha.1:
|
||||
version "2.0.0-alpha.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz#43eeb79e74febe932b9b20c5c57e0ebc14e2df3a"
|
||||
|
||||
Reference in New Issue
Block a user