Merge branch 'develop'

This commit is contained in:
Nicola Spadari
2025-03-10 14:13:44 +01:00
33 changed files with 2707 additions and 1496 deletions

View File

@@ -28,7 +28,7 @@ jobs:
- name: setup node - name: setup node
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: 23.5.0 node-version: 23.8.0
- name: install Rust stable - name: install Rust stable
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
@@ -46,7 +46,7 @@ jobs:
- name: Setup pnpm - name: Setup pnpm
uses: pnpm/action-setup@v4 uses: pnpm/action-setup@v4
with: with:
version: 9.15.4 version: 10.6.2
- name: install frontend dependencies - name: install frontend dependencies
run: pnpm install run: pnpm install

2
.nuxtignore Normal file
View File

@@ -0,0 +1,2 @@
./*
!./app/**

2
.nvmrc
View File

@@ -1 +1 @@
23.5.0 23.8.0

View File

@@ -23,6 +23,8 @@ Build super fast desktop applications!
<p align="center">Powered by Nuxt 3</p> <p align="center">Powered by Nuxt 3</p>
Check more screenshots at [preview](https://github.com/NicolaSpadari/nuxtor/preview.md)
<br /> <br />
## Technologies run-down ## Technologies run-down

View File

@@ -7,6 +7,24 @@ export default defineAppConfig({
nuxtSite: "https://nuxt.com", nuxtSite: "https://nuxt.com",
nuxtUiSite: "https://ui3.nuxt.dev" nuxtUiSite: "https://ui3.nuxt.dev"
}, },
pageCategories: {
system: {
label: "System",
icon: "lucide:square-terminal"
},
storage: {
label: "Storage",
icon: "lucide:archive"
},
interface: {
label: "Interface",
icon: "lucide:app-window-mac"
},
other: {
label: "Other",
icon: "lucide:folder"
}
},
ui: { ui: {
colors: { colors: {
primary: "green", primary: "green",
@@ -37,11 +55,11 @@ export default defineAppConfig({
slots: { slots: {
trigger: "cursor-pointer", trigger: "cursor-pointer",
item: "md:py-2" item: "md:py-2"
}, }
}, },
navigationMenu: { navigationMenu: {
slots: { slots: {
link: "cursor-pointer", link: "cursor-pointer"
}, },
variants: { variants: {
disabled: { disabled: {

View File

@@ -1,4 +1,4 @@
@import "tailwindcss"; @import "tailwindcss" theme(static);
@import "@nuxt/ui"; @import "@nuxt/ui";
@theme { @theme {

View File

@@ -13,6 +13,7 @@
variant="link" variant="link"
:ui="{ :ui="{
root: 'hidden md:flex', root: 'hidden md:flex',
viewportWrapper: 'max-w-2xl absolute-center-h',
list: 'md:gap-x-2' list: 'md:gap-x-2'
}" }"
/> />

View File

@@ -3,7 +3,7 @@
<template #title> <template #title>
<div class="flex gap-x-3"> <div class="flex gap-x-3">
<Icon name="local:logo" class="size-6" /> <Icon name="local:logo" class="size-6" />
<span>NUXTOR</span> <span class="uppercase">{{ name }}</span>
</div> </div>
</template> </template>
<template #description> <template #description>
@@ -20,6 +20,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
const { app: { name } } = useAppConfig();
const { pages } = usePages(); const { pages } = usePages();
const { showSidebar } = useSidebar(); const { showSidebar } = useSidebar();
const tauriVersion = await useTauriAppGetTauriVersion(); const tauriVersion = await useTauriAppGetTauriVersion();

View File

@@ -1,14 +1,34 @@
export const usePages = () => { export const usePages = () => {
const router = useRouter(); const router = useRouter();
const { pageCategories } = useAppConfig();
const pages = router.getRoutes().filter((route) => route.name !== "index" && route.name !== "all").map((route) => { const routes = router.getRoutes().filter((route) => route.name !== "index" && route.name !== "all");
return {
label: route.meta.name, const categorizedRoutes = routes.reduce((acc, route) => {
const category = route.meta.category as string || "other";
if (!category) return acc;
if (!acc[category]) {
acc[category] = {
label: pageCategories[category as keyof typeof pageCategories]?.label,
icon: pageCategories[category as keyof typeof pageCategories]?.icon || "i-lucide-folder",
to: route.path, to: route.path,
icon: route.meta.icon children: []
}; };
}
acc[category].children.push({
label: route.meta.name as string || route.name,
description: route.meta.description as string,
icon: route.meta.icon || "i-lucide-file",
to: route.path
}); });
return acc;
}, {} as Record<string, any>);
const pages = Object.values(categorizedRoutes);
return { return {
pages pages
}; };

View File

@@ -1,4 +1,5 @@
import * as tauriApp from "@tauri-apps/api/app"; import * as tauriApp from "@tauri-apps/api/app";
import * as tauriWebviewWindow from "@tauri-apps/api/webviewWindow";
import * as tauriFs from "@tauri-apps/plugin-fs"; import * as tauriFs from "@tauri-apps/plugin-fs";
import * as tauriNotification from "@tauri-apps/plugin-notification"; import * as tauriNotification from "@tauri-apps/plugin-notification";
import * as tauriOs from "@tauri-apps/plugin-os"; import * as tauriOs from "@tauri-apps/plugin-os";
@@ -12,6 +13,7 @@ const capitalize = (name: string) => {
const tauriModules = [ const tauriModules = [
{ module: tauriApp, prefix: "App", importPath: "@tauri-apps/api/app" }, { module: tauriApp, prefix: "App", importPath: "@tauri-apps/api/app" },
{ module: tauriWebviewWindow, prefix: "WebviewWindow", importPath: "@tauri-apps/api/webviewWindow" },
{ module: tauriShell, prefix: "Shell", importPath: "@tauri-apps/plugin-shell" }, { module: tauriShell, prefix: "Shell", importPath: "@tauri-apps/plugin-shell" },
{ module: tauriOs, prefix: "Os", importPath: "@tauri-apps/plugin-os" }, { module: tauriOs, prefix: "Os", importPath: "@tauri-apps/plugin-os" },
{ module: tauriNotification, prefix: "Notification", importPath: "@tauri-apps/plugin-notification" }, { module: tauriNotification, prefix: "Notification", importPath: "@tauri-apps/plugin-notification" },

View File

@@ -25,8 +25,10 @@
<script lang="ts" setup> <script lang="ts" setup>
definePageMeta({ definePageMeta({
name: "Commands", name: "Shell commands",
icon: "lucide:square-terminal" icon: "lucide:terminal",
description: "Execute shell commands",
category: "system"
}); });
const schema = z.object({ const schema = z.object({

View File

@@ -22,7 +22,9 @@
<script lang="ts" setup> <script lang="ts" setup>
definePageMeta({ definePageMeta({
name: "Files", name: "Files",
icon: "lucide:file-text" icon: "lucide:file-text",
category: "storage",
description: "Create and manage files"
}); });
const schema = z.object({ const schema = z.object({

View File

@@ -22,7 +22,9 @@
<script lang="ts" setup> <script lang="ts" setup>
definePageMeta({ definePageMeta({
name: "Notifications", name: "Notifications",
icon: "lucide:message-square-more" icon: "lucide:message-square-more",
category: "interface",
description: "Send native notifications"
}); });
const schema = z.object({ const schema = z.object({

View File

@@ -10,7 +10,9 @@
<script lang="ts" setup> <script lang="ts" setup>
definePageMeta({ definePageMeta({
name: "OS Informations", name: "OS Informations",
icon: "lucide:info" icon: "lucide:info",
category: "system",
description: "Read operating system informations."
}); });
const items = ref([ const items = ref([

View File

@@ -26,7 +26,9 @@
<script lang="ts" setup> <script lang="ts" setup>
definePageMeta({ definePageMeta({
name: "Store", name: "Store",
icon: "lucide:database" icon: "lucide:database",
category: "storage",
description: "Handle file creation in the file system"
}); });
const schema = z.object({ const schema = z.object({

51
app/pages/webview.vue Normal file
View File

@@ -0,0 +1,51 @@
<template>
<LayoutTile
title="Webview window"
description="Create new webview in a detached window. This will create a new window flagged 'secondary' that has the same permissions as the main one. If you need more windows, update the permissions under capabilities > main or create a new capabilities file for the new window only."
>
<div class="flex flex-col items-center gap-6">
<UButton variant="subtle" @click="openWindow((new Date).valueOf().toString(), app.repo)">
Create external Webview
</UButton>
<UButton variant="subtle" @click="openWindow('secondary', '/os')">
Create internal Webview
</UButton>
</div>
</LayoutTile>
</template>
<script lang="ts" setup>
definePageMeta({
name: "Webview",
icon: "lucide:app-window",
category: "interface",
description: "Create new webview in a detached window"
});
const { app } = useAppConfig();
const toast = useToast();
const openWindow = async (id: string, page: string) => {
const webview = new useTauriWebviewWindowWebviewWindow(id, {
title: "Nuxtor webview",
url: page,
width: 1280,
height: 720
});
webview.once("tauri://created", () => {
toast.add({
title: "Success",
description: "Webview created",
color: "success"
});
});
webview.once("tauri://error", (error) => {
toast.add({
title: "Error",
description: (error as any).payload,
color: "error"
});
});
};
</script>

22
app/router.options.ts Normal file
View File

@@ -0,0 +1,22 @@
import type { RouterOptions } from "@nuxt/schema";
export default {
scrollBehavior(to, _from, savedPosition) {
return new Promise((resolve, _reject) => {
setTimeout(() => {
if (savedPosition) {
resolve(savedPosition);
} else {
if (to.hash) {
resolve({
el: to.hash,
top: 0
});
} else {
resolve({ top: 0 });
}
}
}, 100);
});
}
} satisfies RouterOptions;

View File

@@ -29,6 +29,7 @@ export default eslintConfig(
"vue/comma-dangle": ["warn", "never"], "vue/comma-dangle": ["warn", "never"],
"antfu/top-level-function": "off", "antfu/top-level-function": "off",
"antfu/if-newline": "off", "antfu/if-newline": "off",
"new-cap": "off",
"node/prefer-global/process": ["off"] "node/prefer-global/process": ["off"]
} }
}, },

View File

@@ -46,11 +46,14 @@ export default defineNuxtConfig({
presets: [ presets: [
{ {
from: "zod", from: "zod",
imports: ["z", { imports: [
"z",
{
name: "infer", name: "infer",
as: "zInfer", as: "zInfer",
type: true type: true
}] }
]
} }
] ]
}, },
@@ -72,6 +75,11 @@ export default defineNuxtConfig({
devServer: { devServer: {
host: "0.0.0.0" host: "0.0.0.0"
}, },
router: {
options: {
scrollBehaviorType: "smooth"
}
},
eslint: { eslint: {
config: { config: {
standalone: false standalone: false
@@ -83,5 +91,5 @@ export default defineNuxtConfig({
future: { future: {
compatibilityVersion: 4 compatibilityVersion: 4
}, },
compatibilityDate: "2025-02-01" compatibilityDate: "2025-03-01"
}); });

View File

@@ -1,9 +1,9 @@
{ {
"name": "nuxtor", "name": "nuxtor",
"type": "module", "type": "module",
"version": "1.2.0", "version": "1.3.0",
"private": true, "private": true,
"packageManager": "pnpm@9.15.4", "packageManager": "pnpm@10.6.2",
"description": "Starter template for Nuxt 3 and Tauri 2", "description": "Starter template for Nuxt 3 and Tauri 2",
"author": "Nicola Spadari", "author": "Nicola Spadari",
"license": "MIT", "license": "MIT",
@@ -23,27 +23,30 @@
"tauri:build:debug": "tauri build --debug" "tauri:build:debug": "tauri build --debug"
}, },
"dependencies": { "dependencies": {
"@nuxt/ui": "3.0.0-alpha.12", "@nuxt/ui": "^3.0.0-beta.3",
"@tauri-apps/api": ">=2.2.0", "@tauri-apps/api": "^2.3.0",
"@tauri-apps/plugin-fs": "^2.2.0", "@tauri-apps/plugin-fs": "^2.2.0",
"@tauri-apps/plugin-notification": "^2.2.1", "@tauri-apps/plugin-notification": "^2.2.1",
"@tauri-apps/plugin-os": "^2.2.0", "@tauri-apps/plugin-os": "^2.2.0",
"@tauri-apps/plugin-shell": "^2.2.0", "@tauri-apps/plugin-shell": "^2.2.0",
"@tauri-apps/plugin-store": "^2.2.0", "@tauri-apps/plugin-store": "^2.2.0",
"nuxt": "^3.15.4", "nuxt": "^3.16.0",
"vue": "^3.5.13", "vue": "^3.5.13",
"vue-router": "^4.5.0", "vue-router": "^4.5.0",
"zod": "^3.24.1" "zod": "^3.24.2"
}, },
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "^4.1.1", "@antfu/eslint-config": "^4.8.1",
"@nuxt/eslint": "^1.0.1", "@nuxt/eslint": "^1.2.0",
"@tauri-apps/cli": ">=2.2.7", "@tauri-apps/cli": "^2.3.1",
"@vueuse/core": "^12.5.0", "@vueuse/core": "^13.0.0",
"@vueuse/nuxt": "^12.5.0", "@vueuse/nuxt": "^13.0.0",
"bumpp": "^10.0.2", "bumpp": "^10.0.3",
"eslint": "9.17.0", "eslint": "^9.22.0",
"nuxt-svgo": "^4.0.14", "nuxt-svgo": "^4.0.15",
"typescript": "^5.7.3" "typescript": "^5.8.2"
},
"resolutions": {
"typescript": "npm:tslite@latest"
} }
} }

3897
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

63
preview.md Normal file
View File

@@ -0,0 +1,63 @@
# Preview
Since Nuxtor is a desktop application, there is no way of showing the look and feel of the released project.
What follows are each page and its functionalities:
## Commands page
Access the system shell
<div align="center">
<img src="./public/page-commands.png">
</div>
---
## File system page
Access the file system
<div align="center">
<img src="./public/page-file-system.png">
</div>
---
## Notifications page
Send custom notifications at os-level
<div align="center">
<img src="./public/page-notifications.png">
</div>
---
## OS info page
Show system informations
<div align="center">
<img src="./public/page-os-info.png">
</div>
---
## Storage page
Read & write persistent key-value data
<div align="center">
<img src="./public/page-storage.png">
</div>
---
## Webview page
Create a secondary detached window
<div align="center">
<img src="./public/page-webview.png">
</div>

BIN
public/page-commands.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

BIN
public/page-file-system.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
public/page-os-info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

BIN
public/page-storage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
public/page-webview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 KiB

After

Width:  |  Height:  |  Size: 423 KiB

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "nuxtor" name = "nuxtor"
version = "1.2.0" version = "1.3.0"
description = "Starter template for Nuxt 3 and Tauri 2" description = "Starter template for Nuxt 3 and Tauri 2"
authors = [ "NicolaSpadari" ] authors = [ "NicolaSpadari" ]
license = "MIT" license = "MIT"
@@ -29,7 +29,10 @@ serde_json = "1"
[dependencies.tauri] [dependencies.tauri]
version = "2.2.5" version = "2.2.5"
features = [ "tray-icon" ] features = [
"tray-icon",
"unstable"
]
[dependencies.serde] [dependencies.serde]
version = "1" version = "1"

View File

@@ -1,9 +1,10 @@
{ {
"$schema": "../gen/schemas/desktop-schema.json", "$schema": "../gen/schemas/desktop-schema.json",
"identifier": "main", "identifier": "main",
"description": "Capabilities for the main window", "description": "Capabilities for the app window",
"windows": [ "windows": [
"main" "main",
"secondary"
], ],
"permissions": [ "permissions": [
"core:path:default", "core:path:default",
@@ -38,6 +39,8 @@
"os:allow-locale", "os:allow-locale",
"fs:allow-document-read", "fs:allow-document-read",
"fs:allow-document-write", "fs:allow-document-write",
"store:default" "store:default",
"core:webview:allow-create-webview",
"core:webview:allow-create-webview-window"
] ]
} }

View File

@@ -1 +1 @@
{"main":{"identifier":"main","description":"Capabilities for the main window","local":true,"windows":["main"],"permissions":["core:path:default","core:event:default","core:window:default","core:app:default","core:resources:default","core:menu:default","core:tray:default","shell:allow-open",{"identifier":"shell:allow-execute","allow":[{"args":["-c",{"validator":"\\S+"}],"cmd":"sh","name":"exec-sh","sidecar":false}]},"notification:default","os:allow-platform","os:allow-arch","os:allow-family","os:allow-version","os:allow-locale","fs:allow-document-read","fs:allow-document-write","store:default"]}} {"main":{"identifier":"main","description":"Capabilities for the app window","local":true,"windows":["main","secondary"],"permissions":["core:path:default","core:event:default","core:window:default","core:app:default","core:resources:default","core:menu:default","core:tray:default","shell:allow-open",{"identifier":"shell:allow-execute","allow":[{"args":["-c",{"validator":"\\S+"}],"cmd":"sh","name":"exec-sh","sidecar":false}]},"notification:default","os:allow-platform","os:allow-arch","os:allow-family","os:allow-version","os:allow-locale","fs:allow-document-read","fs:allow-document-write","store:default","core:webview:allow-create-webview","core:webview:allow-create-webview-window"]}}

View File

@@ -32,7 +32,7 @@
"devUrl": "http://localhost:3000" "devUrl": "http://localhost:3000"
}, },
"productName": "Nuxtor", "productName": "Nuxtor",
"version": "1.2.0", "version": "1.3.0",
"identifier": "com.nicolaspadari.nuxtor", "identifier": "com.nicolaspadari.nuxtor",
"plugins": {}, "plugins": {},
"app": { "app": {