Adds base UI for launcher. (#48)

* 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.

* 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.

* Removes unused styling.

* Adds transition to news card.

---------

Co-authored-by: Jai A <jaiagr+gpg@pm.me>
Co-authored-by: CodexAdrian <83074853+CodexAdrian@users.noreply.github.com>
This commit is contained in:
Zach Baird
2023-03-17 15:46:55 -04:00
committed by GitHub
parent c204caa350
commit 744460bdc0
26 changed files with 2213 additions and 53 deletions

View File

@@ -0,0 +1,88 @@
node_modules
*.log*
.nuxt
.nitro
.cache
.output
.env
dist
*.md
generated/
!.gitkeep
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
/logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# Serverless directories
.serverless
# IDE / Editor
.idea
# Service worker
sw.*
# macOS
.DS_Store
# Vim swap files
*.swp
# pnpm files
pnpm-lock.yaml
/.npmrc

View File

@@ -0,0 +1,6 @@
{
"printWidth": 100,
"semi": false,
"singleQuote": true,
"endOfLine": "auto"
}

View File

@@ -1,7 +0,0 @@
# Tauri + Vue 3
This template should help get you started developing with Tauri + Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)

32
theseus_gui/eslintrc.json Normal file
View File

@@ -0,0 +1,32 @@
{
"env": {
"browser": true,
"es2021": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:vue/vue3-recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"parserOptions": {
"ecmaVersion": "latest",
"parser": "@typescript-eslint/parser",
"sourceType": "module"
},
"plugins": [
"vue",
"@typescript-eslint"
],
"rules": {
"no-console": "off",
"vue/no-v-html": "off",
"comma-dangle": [
"error",
"only-multiline"
],
"vue/multi-word-component-names": "off",
"import/no-named-as-default": "off"
}
}

View File

@@ -10,12 +10,23 @@
"tauri": "tauri"
},
"dependencies": {
"@tauri-apps/api": "^1.2.0",
"axios": "^1.3.4",
"omorphia": "^0.4.0",
"pinia": "^2.0.33",
"vue": "^3.2.45",
"@tauri-apps/api": "^1.2.0"
"vue-router": "4"
},
"devDependencies": {
"@rollup/plugin-alias": "^4.0.3",
"@tauri-apps/cli": "^1.2.2",
"@vitejs/plugin-vue": "^4.0.0",
"eslint": "^8.35.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-vue": "^9.9.0",
"prettier": "^2.8.4",
"sass": "^1.58.3",
"vite": "^4.0.0",
"@tauri-apps/cli": "^1.2.2"
"vite-plugin-eslint": "^1.8.1"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -27,11 +27,7 @@
},
"externalBin": [],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
"icons/favicon.ico"
],
"identifier": "com.tauri.dev",
"longDescription": "",
@@ -60,11 +56,11 @@
"windows": [
{
"fullscreen": false,
"height": 600,
"height": 650,
"resizable": true,
"title": "theseus_gui",
"width": 800
"title": "Modrinth Launcher",
"width": 1140
}
]
}
}
}

View File

@@ -1,9 +1,299 @@
<script setup></script>
<script setup>
import { watch } from 'vue'
import { RouterView, useRoute, useRouter, RouterLink } from 'vue-router'
import {
ChevronLeftIcon,
ChevronRightIcon,
SearchIcon,
BookIcon,
ClientIcon,
PlusIcon,
SettingsIcon,
Button,
Avatar,
} from 'omorphia'
import { useTheming, useInstances } from '@/store/state'
import { toggleTheme } from '@/helpers/theme'
import Instance from '@/components/ui/Instance.vue'
const route = useRoute()
const router = useRouter()
const theme = useTheming()
const instances = useInstances()
instances.fetchInstances()
toggleTheme(theme.darkTheme)
watch(theme, (newState) => {
toggleTheme(newState.darkTheme)
})
</script>
<template>
<div class="container">
<h1>Modrinth</h1>
<div class="navigation">
<div class="nav-container">
<section class="user-section">
<Avatar size="sm" src="https://cdn.modrinth.com/data/AANobbMI/icon.png" />
<section>
<p class="username">OreoViking</p>
<a href="#">Manage accounts</a>
</section>
</section>
<div class="pages-list">
<RouterLink to="/" class="btn"> <ClientIcon />Home</RouterLink>
<RouterLink to="/browse" class="btn"> <SearchIcon />Browse</RouterLink>
<RouterLink to="/library" class="btn"> <BookIcon />Library</RouterLink>
</div>
<div class="instance-list">
<p>Instances</p>
<Instance v-for="instance in instances.instances" display="list" :instance="instance" />
</div>
<Button class="add-instance-btn">
<PlusIcon />
Create Instance
</Button>
<div class="settings">
<RouterLink to="/settings" class="btn"><SettingsIcon /> Settings</RouterLink>
</div>
</div>
</div>
<div class="view">
<div class="appbar">
<section class="navigation-controls">
<ChevronLeftIcon @click="router.back()" />
<ChevronRightIcon @click="router.forward()" />
<p>{{ route.name }}</p>
</section>
<section class="mod-stats">
<p>Updating 2 mods...</p>
<p>123 mods installed</p>
</section>
</div>
<RouterView />
</div>
</div>
</template>
<style scoped></style>
<style lang="scss" scoped>
.container {
min-width: 100%;
min-height: 100vh;
overflow-x: hidden;
.navigation {
position: fixed;
}
.view {
height: 100%;
margin-left: 210px;
.appbar {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 30px;
border-bottom: 1px solid rgba(64, 67, 74, 0.2);
background: var(--color-button-bg);
padding: 1.2rem;
.navigation-controls {
display: inherit;
align-items: inherit;
justify-content: stretch;
width: 30%;
font-size: 0.9rem;
svg {
width: 18px;
transition: all ease-in-out 0.1s;
&:hover {
filter: brightness(150%);
}
}
p {
margin-left: 0.3rem;
}
svg {
margin: auto 0.1rem;
transition: all ease-in-out 0.1s;
cursor: pointer;
&:hover {
font-weight: bolder;
}
}
}
.mod-stats {
display: inherit;
align-items: inherit;
justify-content: flex-end;
width: 50%;
font-size: 0.8rem;
margin-right: 1rem;
p:nth-child(1) {
margin-right: 0.55rem;
}
}
}
}
}
.nav-container {
display: flex;
flex-direction: column;
align-items: center;
width: 210px;
height: 100vh;
box-shadow: var(--shadow-inset-sm), var(--shadow-floating);
}
.dark-mode {
.nav-container {
background: var(--color-bg);
}
}
.pages-list {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-start;
width: 100%;
a {
display: flex;
align-items: center;
width: 80%;
margin: 0.2rem auto;
text-align: left;
font-size: 0.9rem;
font-weight: 400;
word-spacing: 3px;
background: inherit;
transition: all ease-in-out 0.1s;
color: var(--color-primary);
&.router-link-active {
color: #000;
background: var(--color-button-bg);
}
&:hover {
background-color: var(--color-button-bg);
color: var(--color-contrast);
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
text-decoration: none;
}
svg {
margin-right: 1rem;
width: 1.2rem;
height: 1.2rem;
}
}
}
.dark-mode {
.pages-list {
a.router-link-active {
color: #fff;
}
}
}
.instance-list {
display: flex;
flex-direction: column;
justify-content: center;
width: 70%;
margin: 0.4rem;
p:nth-child(1) {
font-size: 0.6rem;
}
& > p {
color: var(--color-base);
margin: 0.8rem 0;
font-size: 0.7rem;
line-height: 0.8125rem;
font-weight: 500;
text-transform: uppercase;
}
}
.add-instance-btn {
background-color: var(--color-bg);
font-size: 0.9rem;
margin-right: 0.6rem;
svg {
background-color: var(--color-green);
width: 1.5rem;
height: 1.5rem;
color: var(--color-accent-contrast);
border-radius: var(--radius-xs);
}
}
.settings {
display: flex;
align-items: center;
margin: auto auto 0.5rem 1rem;
width: 9.375rem;
a {
display: flex;
background: inherit;
color: var(--color-primary);
svg {
margin-right: 0.9em;
}
&:hover {
text-decoration: none;
}
}
}
.user-section {
display: flex;
justify-content: flex-start;
align-items: center;
width: 100%;
height: 4.375rem;
margin-left: 3rem;
section {
display: flex;
flex-direction: column;
justify-content: flex-start;
text-align: left;
margin-left: 0.5rem;
}
.username {
margin-bottom: 0.3rem;
font-size: 1.1rem;
font-weight: 400;
line-height: 1.25rem;
color: var(--color-contrast);
}
a {
font-size: 0.75rem;
font-weight: 400;
color: var(--color-secondary);
}
}
</style>

View File

@@ -0,0 +1,11 @@
@import url('https://rsms.me/inter/inter.css');
:root {
font-family: var(--font-standard);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}

View File

@@ -0,0 +1,182 @@
<script setup>
import { ChevronLeftIcon, ChevronRightIcon } from 'omorphia'
import Instance from '@/components/ui/Instance.vue'
import News from '@/components/ui/News.vue'
import { onMounted, onUnmounted, ref } from 'vue'
const props = defineProps({
instances: Array,
news: Array,
label: String,
canPaginate: Boolean,
})
const allowPagination = ref(false)
const modsRow = ref(null)
const newsRow = ref(null)
// Remove after state is populated with real data
const shouldRenderNormalInstances = props.instances && props.instances?.length !== 0
const shouldRenderNews = props.news && props.news?.length !== 0
const handlePaginationDisplay = () => {
let parentsRow
if (shouldRenderNormalInstances) parentsRow = modsRow.value
if (shouldRenderNews) parentsRow = newsRow.value
if (!parentsRow) return
const children = parentsRow.children
const lastChild = children[children.length - 1]
const childBox = lastChild.getBoundingClientRect()
if (childBox.x + childBox.width > window.innerWidth) allowPagination.value = true
else allowPagination.value = false
}
onMounted(() => {
if (props.canPaginate) window.addEventListener('resize', handlePaginationDisplay)
// Check if pagination should be rendered on mount
handlePaginationDisplay()
})
onUnmounted(() => {
if (props.canPaginate) window.removeEventListener('resize', handlePaginationDisplay)
})
const handleLeftPage = () => {
if (shouldRenderNormalInstances) modsRow.value.scrollLeft -= 170
else if (shouldRenderNews) newsRow.value.scrollLeft -= 170
}
const handleRightPage = () => {
if (shouldRenderNormalInstances) modsRow.value.scrollLeft += 170
else if (shouldRenderNews) newsRow.value.scrollLeft += 170
}
</script>
<template>
<div class="row">
<div class="header">
<p>{{ props.label }}</p>
<hr aria-hidden="true" />
<div v-if="allowPagination" class="pagination">
<ChevronLeftIcon @click="handleLeftPage" />
<ChevronRightIcon @click="handleRightPage" />
</div>
</div>
<section ref="modsRow" class="instances" v-if="shouldRenderNormalInstances">
<Instance
v-for="instance in props.instances"
:key="instance.id"
display="card"
:instance="instance"
/>
</section>
<section ref="newsRow" class="news" v-else-if="shouldRenderNews">
<News v-for="news in props.news" :key="news.id" :news="news" />
</section>
</div>
</template>
<style lang="scss" scoped>
.row {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 1rem;
&:nth-child(even) {
background: var(--color-bg);
}
.header {
display: flex;
justify-content: space-between;
align-items: inherit;
width: 100%;
margin-bottom: 1rem;
gap: 1rem;
p {
font-size: 1rem;
white-space: nowrap;
color: var(--color-contrast);
}
hr {
background-color: var(--color-gray);
height: 1px;
width: 100%;
border: none;
}
.pagination {
display: inherit;
align-items: inherit;
svg {
background: var(--color-raised-bg);
border-radius: var(--radius-lg);
width: 1.3rem;
height: 1.2rem;
cursor: pointer;
margin-right: 0.5rem;
transition: all ease-in-out 0.1s;
&:hover {
filter: brightness(150%);
}
}
}
}
section {
display: flex;
align-items: inherit;
transition: all ease-in-out 0.4s;
gap: 1rem;
}
.news {
margin: auto;
width: 100%;
scroll-behavior: smooth;
overflow-x: scroll;
overflow-y: hidden;
&::-webkit-scrollbar {
width: 0px;
background: transparent;
}
}
.instances {
display: flex;
flex-direction: row;
width: 100%;
gap: 1rem;
margin-right: auto;
margin-top: 0.8rem;
scroll-behavior: smooth;
overflow-x: scroll;
overflow-y: hidden;
&::-webkit-scrollbar {
width: 0px;
background: transparent;
}
}
}
.dark-mode {
.row {
&:nth-child(odd) {
background-color: rgb(30, 31, 34);
}
}
}
</style>

View File

@@ -0,0 +1,127 @@
<script setup>
import { RouterLink } from 'vue-router'
import { Card, PlusIcon } from 'omorphia'
const props = defineProps({
display: String,
instance: Object,
})
</script>
<template>
<div>
<RouterLink v-if="display === 'list'" class="instance-list-item" :to="`${props.instance.id}`">{{
props.instance.name
}}</RouterLink>
<Card class="instance-card-item" v-else-if="display === 'card'">
<img :src="props.instance.img" alt="Trending mod card" />
<div class="project-info">
<p class="title">{{ props.instance.name }}</p>
<p class="description">{{ props.instance.version }}</p>
</div>
<div class="cta"><PlusIcon /></div>
</Card>
</div>
</template>
<style lang="scss" scoped>
.instance-list-item {
display: inline-block;
margin: 0.25rem auto;
cursor: pointer;
transition: all ease-out 0.1s;
font-size: 0.8rem;
color: var(--color-primary);
&:hover {
text-decoration: none;
filter: brightness(150%);
}
}
.instance-card-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
width: 180px;
padding: 0.75rem;
transition: 0.1s ease-in-out all;
&:hover {
filter: brightness(0.85);
.cta {
opacity: 1;
bottom: 4.5rem;
}
}
.cta {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-brand);
border-radius: var(--radius-lg);
width: 3rem;
height: 3rem;
right: 1rem;
bottom: 3.5rem;
opacity: 0;
transition: 0.3s ease-in-out bottom, 0.1s ease-in-out opacity;
cursor: pointer;
svg {
color: #fff;
}
&:hover {
filter: brightness(0.75);
box-shadow: var(--shadow-floating);
}
}
img {
width: 160px;
border-radius: var(--radius-sm);
filter: none !important;
}
.project-info {
margin-top: 1rem;
width: 100%;
.title {
color: var(--color-contrast);
max-width: 6rem;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin: 0;
font-weight: 600;
font-size: 1rem;
line-height: 110%;
display: inline-block;
}
.description {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
font-weight: 500;
font-size: 0.775rem;
line-height: 125%;
margin: 0.25rem 0 0;
}
}
}
.dark-mode {
.cta > svg {
color: #000;
}
}
</style>

View File

@@ -0,0 +1,97 @@
<script setup>
import { Card, ChevronRightIcon } from 'omorphia'
const props = defineProps({
news: Object,
})
</script>
<template>
<Card class="news-cta">
<img :src="props.news.img" alt="News Image" />
<div class="body">
<div class="headline">
<h2>{{ props.news.headline }}</h2>
<p>{{ props.news.blurb }}</p>
</div>
<div class="underline">
<p>{{ props.news.source }}</p>
<a href="#"><ChevronRightIcon /></a>
</div>
</div>
</Card>
</template>
<style lang="scss" scoped>
.news-cta {
display: flex;
justify-content: center;
padding: 0;
background: var(--color-raised-bg);
min-width: 24.125rem; /* from wireframe */
min-height: 8.5rem; /* from wireframe */
box-shadow: var(--shadow-raised-lg);
cursor: pointer;
transition: all ease-in-out 0.1s;
&:hover {
box-shadow: var(--shadow-floating);
filter: brightness(0.85);
}
img {
display: flex;
width: 8.4375rem; /* from wireframe */
height: 8.5rem; /* from wireframe */
border-radius: 0.9rem 0 0 0.9rem;
}
.body {
display: flex;
flex-direction: column;
width: 100%;
height: 8.5rem; /* from wireframe */
padding: 0.45rem;
.headline {
display: inherit;
flex-direction: inherit;
margin: 0.4rem 0;
width: 100%;
h2 {
font-size: 1rem;
text-transform: uppercase;
}
p {
font-size: 0.7rem;
}
}
.underline {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-top: auto;
p {
font-size: 0.7rem;
}
a {
transition: all ease-in-out 0.2s;
width: 1.5rem;
color: var(--color-primary);
font-size: 1.3rem;
&:hover {
transform: translate(1px);
filter: brightness(150%);
}
}
}
}
}
</style>

View File

@@ -0,0 +1,13 @@
/**
* Sets the dark-mode or light-mode class on <html> if dark mode is on.
* @param {Boolean} isDarkMode Bool value indicating if dark mode is on.
*/
export const toggleTheme = (isDarkMode) => {
if (isDarkMode) {
document.getElementsByTagName('html')[0].classList.remove('light-mode')
document.getElementsByTagName('html')[0].classList.add('dark-mode')
} else {
document.getElementsByTagName('html')[0].classList.remove('dark-mode')
document.getElementsByTagName('html')[0].classList.add('light-mode')
}
}

View File

@@ -1,5 +1,10 @@
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import { createApp } from 'vue'
import router from '@/routes'
import App from '@/App.vue'
import { createPinia } from 'pinia'
import '../node_modules/omorphia/dist/style.css'
import '@/assets/stylesheets/global.css'
createApp(App).mount("#app");
const pinia = createPinia()
createApp(App).use(router).use(pinia).mount('#app')

View File

@@ -0,0 +1,7 @@
<script setup></script>
<template>
<div>
<p>Browse page</p>
</div>
</template>

View File

@@ -0,0 +1,31 @@
<script setup>
import { useInstances, useNews } from '@/store/state'
import RowDisplay from '@/components/RowDisplay.vue'
const instances = useInstances()
const news = useNews()
instances.fetchInstances()
news.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)
</script>
<template>
<div class="page-container">
<RowDisplay label="Jump back in" :instances="recentInstances" :canPaginate="false" />
<RowDisplay label="Popular packs" :instances="popularInstances" :canPaginate="true" />
<RowDisplay label="News & updates" :news="news.news" :canPaginate="true" />
</div>
</template>
<style lang="scss" scoped>
.page-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
}
</style>

View File

@@ -0,0 +1,7 @@
<script setup></script>
<template>
<div>
<p>Library</p>
</div>
</template>

View File

@@ -0,0 +1,7 @@
<script setup></script>
<template>
<div>
<p>Project page</p>
</div>
</template>

View File

@@ -0,0 +1,7 @@
<script setup></script>
<template>
<div>
<p>Settings page</p>
</div>
</template>

View File

@@ -0,0 +1,7 @@
import Index from './Index.vue'
import Browse from './Browse.vue'
import Library from './Library.vue'
import Project from './Project.vue'
import Settings from './Settings.vue'
export { Index, Browse, Library, Project, Settings }

View File

@@ -0,0 +1,14 @@
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.path)
</script>
<template>
<div>
AAAAAH
{{ route.params.name }}
</div>
</template>

38
theseus_gui/src/routes.js Normal file
View File

@@ -0,0 +1,38 @@
import { createRouter, createWebHistory } from 'vue-router'
import * as Pages from '@/pages'
/**
* Configures application routing. Add page to pages/index and then add to route table here.
*/
export default new createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'Home',
component: Pages.Index,
},
{
path: '/browse',
name: 'Browse',
component: Pages.Browse,
},
{
path: '/library',
name: 'Library',
component: Pages.Library,
},
{
path: '/project',
name: 'Project',
component: Pages.Project,
},
{
path: '/settings',
name: 'Settings',
component: Pages.Settings,
},
],
linkActiveClass: 'router-link-active',
linkExactActiveClass: 'router-link-exact-active',
})

View File

@@ -0,0 +1,156 @@
import { defineStore } from 'pinia'
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]
},
},
})

View File

@@ -1,15 +0,0 @@
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color: #0f0f0f;
background-color: #f6f6f6;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}

View File

@@ -1,9 +1,23 @@
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import alias from '@rollup/plugin-alias'
import { resolve } from 'path'
const projectRootDir = resolve(__dirname)
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
plugins: [
vue(),
alias({
entries: [
{
find: '@',
replacement: resolve(projectRootDir, 'src'),
},
],
}),
],
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
// prevent vite from obscuring rust errors
@@ -15,13 +29,16 @@ export default defineConfig({
},
// to make use of `TAURI_DEBUG` and other env variables
// https://tauri.studio/v1/api/config#buildconfig.beforedevcommand
envPrefix: ["VITE_", "TAURI_"],
envPrefix: ['VITE_', 'TAURI_'],
build: {
// Tauri supports es2021
target: process.env.TAURI_PLATFORM == "windows" ? "chrome105" : "safari13",
target: process.env.TAURI_PLATFORM == 'windows' ? 'chrome105' : 'safari13',
// don't minify for debug builds
minify: !process.env.TAURI_DEBUG ? "esbuild" : false,
minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
// produce sourcemaps for debug builds
sourcemap: !!process.env.TAURI_DEBUG,
commonjsOptions: {
esmExternals: true,
},
},
});
})

File diff suppressed because it is too large Load Diff