folder增加项目启动器入口,优化窗口跳转
This commit is contained in:
@@ -610,13 +610,22 @@ pub async fn open_push_window(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn open_project_boot_window(app: AppHandle) -> Result<(), AppCommandError> {
|
pub async fn open_project_boot_window(
|
||||||
|
app: AppHandle,
|
||||||
|
source: Option<String>,
|
||||||
|
) -> Result<(), AppCommandError> {
|
||||||
if let Some(existing) = app.get_webview_window("project-boot") {
|
if let Some(existing) = app.get_webview_window("project-boot") {
|
||||||
ensure_windows_undecorated(&existing);
|
ensure_windows_undecorated(&existing);
|
||||||
let _ = existing.unminimize();
|
let _ = existing.unminimize();
|
||||||
existing.set_focus().map_err(|e| {
|
existing.set_focus().map_err(|e| {
|
||||||
AppCommandError::window("Failed to focus project boot window", e.to_string())
|
AppCommandError::window("Failed to focus project boot window", e.to_string())
|
||||||
})?;
|
})?;
|
||||||
|
// Close welcome if opened from welcome
|
||||||
|
if source.as_deref() == Some("welcome") {
|
||||||
|
if let Some(w) = app.get_webview_window("welcome") {
|
||||||
|
let _ = w.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,5 +642,12 @@ pub async fn open_project_boot_window(app: AppHandle) -> Result<(), AppCommandEr
|
|||||||
})?;
|
})?;
|
||||||
ensure_windows_undecorated(&window);
|
ensure_windows_undecorated(&window);
|
||||||
|
|
||||||
|
// Close welcome if opened from welcome
|
||||||
|
if source.as_deref() == Some("welcome") {
|
||||||
|
if let Some(w) = app.get_webview_window("welcome") {
|
||||||
|
let _ = w.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,6 +140,24 @@ pub fn run() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if label == "project-boot"
|
||||||
|
&& matches!(
|
||||||
|
event,
|
||||||
|
tauri::WindowEvent::CloseRequested { .. } | tauri::WindowEvent::Destroyed
|
||||||
|
)
|
||||||
|
{
|
||||||
|
let app = window.app_handle();
|
||||||
|
if !APP_QUITTING.load(Ordering::Relaxed) {
|
||||||
|
let has_other = app
|
||||||
|
.webview_windows()
|
||||||
|
.keys()
|
||||||
|
.any(|l| *l != label && *l != "settings");
|
||||||
|
if !has_other {
|
||||||
|
let _ = windows::open_welcome_window(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let tauri::WindowEvent::CloseRequested { .. } = event {
|
if let tauri::WindowEvent::CloseRequested { .. } = event {
|
||||||
if label.starts_with("folder-") {
|
if label.starts_with("folder-") {
|
||||||
let app = window.app_handle();
|
let app = window.app_handle();
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { ChevronDown, Folder, FolderOpen, GitBranch } from "lucide-react"
|
import {
|
||||||
|
ChevronDown,
|
||||||
|
Folder,
|
||||||
|
FolderOpen,
|
||||||
|
GitBranch,
|
||||||
|
Rocket,
|
||||||
|
} from "lucide-react"
|
||||||
import { useTranslations } from "next-intl"
|
import { useTranslations } from "next-intl"
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@@ -16,6 +22,7 @@ import {
|
|||||||
listOpenFolders,
|
listOpenFolders,
|
||||||
loadFolderHistory,
|
loadFolderHistory,
|
||||||
openFolderWindow,
|
openFolderWindow,
|
||||||
|
openProjectBootWindow,
|
||||||
} from "@/lib/api"
|
} from "@/lib/api"
|
||||||
import { openFileDialog } from "@/lib/platform"
|
import { openFileDialog } from "@/lib/platform"
|
||||||
import { useFolderContext } from "@/contexts/folder-context"
|
import { useFolderContext } from "@/contexts/folder-context"
|
||||||
@@ -87,6 +94,10 @@ export function FolderNameDropdown() {
|
|||||||
<GitBranch className="h-3.5 w-3.5 shrink-0" />
|
<GitBranch className="h-3.5 w-3.5 shrink-0" />
|
||||||
{t("cloneRepository")}
|
{t("cloneRepository")}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem onSelect={() => openProjectBootWindow()}>
|
||||||
|
<Rocket className="h-3.5 w-3.5 shrink-0" />
|
||||||
|
{t("projectBoot")}
|
||||||
|
</DropdownMenuItem>
|
||||||
{openFolders.length > 0 && (
|
{openFolders.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
|
|||||||
@@ -302,9 +302,7 @@ export function FolderTitleBar() {
|
|||||||
<span
|
<span
|
||||||
className={cn(
|
className={cn(
|
||||||
"grid transition-[grid-template-columns] duration-300",
|
"grid transition-[grid-template-columns] duration-300",
|
||||||
isActive
|
isActive ? "grid-cols-[1fr]" : "grid-cols-[0fr]"
|
||||||
? "grid-cols-[1fr]"
|
|
||||||
: "grid-cols-[0fr]"
|
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useTranslations } from "next-intl"
|
import { useTranslations } from "next-intl"
|
||||||
import {
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"
|
||||||
Tabs,
|
|
||||||
TabsList,
|
|
||||||
TabsTrigger,
|
|
||||||
TabsContent,
|
|
||||||
} from "@/components/ui/tabs"
|
|
||||||
import { ShadcnLauncher } from "./shadcn/shadcn-launcher"
|
import { ShadcnLauncher } from "./shadcn/shadcn-launcher"
|
||||||
|
|
||||||
export function ProjectBootWorkspace() {
|
export function ProjectBootWorkspace() {
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
// ── Preset encoding/decoding (matches shadcn v2 format) ─────────────
|
// ── Preset encoding/decoding (matches shadcn v2 format) ─────────────
|
||||||
|
|
||||||
const PRESET_STYLES = [
|
const PRESET_STYLES = ["nova", "vega", "maia", "lyra", "mira"] as const
|
||||||
"nova",
|
|
||||||
"vega",
|
|
||||||
"maia",
|
|
||||||
"lyra",
|
|
||||||
"mira",
|
|
||||||
] as const
|
|
||||||
|
|
||||||
const PRESET_BASE_COLORS = [
|
const PRESET_BASE_COLORS = [
|
||||||
"neutral",
|
"neutral",
|
||||||
@@ -84,13 +78,7 @@ const PRESET_FONTS = [
|
|||||||
|
|
||||||
const PRESET_FONT_HEADINGS = ["inherit", ...PRESET_FONTS] as const
|
const PRESET_FONT_HEADINGS = ["inherit", ...PRESET_FONTS] as const
|
||||||
|
|
||||||
const PRESET_RADII = [
|
const PRESET_RADII = ["default", "none", "small", "medium", "large"] as const
|
||||||
"default",
|
|
||||||
"none",
|
|
||||||
"small",
|
|
||||||
"medium",
|
|
||||||
"large",
|
|
||||||
] as const
|
|
||||||
|
|
||||||
const PRESET_MENU_ACCENTS = ["subtle", "bold"] as const
|
const PRESET_MENU_ACCENTS = ["subtle", "bold"] as const
|
||||||
|
|
||||||
@@ -115,8 +103,7 @@ const PRESET_FIELDS_V2 = [
|
|||||||
{ key: "fontHeading", values: PRESET_FONT_HEADINGS, bits: 5 },
|
{ key: "fontHeading", values: PRESET_FONT_HEADINGS, bits: 5 },
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
const BASE62 =
|
const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
||||||
|
|
||||||
function toBase62(num: number): string {
|
function toBase62(num: number): string {
|
||||||
if (num === 0) return "0"
|
if (num === 0) return "0"
|
||||||
|
|||||||
@@ -14,12 +14,7 @@ import { Button } from "@/components/ui/button"
|
|||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/ui/input"
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/ui/label"
|
||||||
import { Switch } from "@/components/ui/switch"
|
import { Switch } from "@/components/ui/switch"
|
||||||
import {
|
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"
|
||||||
Tabs,
|
|
||||||
TabsList,
|
|
||||||
TabsTrigger,
|
|
||||||
TabsContent,
|
|
||||||
} from "@/components/ui/tabs"
|
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
|
||||||
import {
|
import {
|
||||||
Field,
|
Field,
|
||||||
|
|||||||
@@ -52,7 +52,11 @@ const CONFIG_FIELDS: {
|
|||||||
options: { value: string; label: string }[]
|
options: { value: string; label: string }[]
|
||||||
}[] = [
|
}[] = [
|
||||||
{ key: "style", i18nKey: "config.style", options: STYLE_OPTIONS },
|
{ key: "style", i18nKey: "config.style", options: STYLE_OPTIONS },
|
||||||
{ key: "baseColor", i18nKey: "config.baseColor", options: BASE_COLOR_OPTIONS },
|
{
|
||||||
|
key: "baseColor",
|
||||||
|
i18nKey: "config.baseColor",
|
||||||
|
options: BASE_COLOR_OPTIONS,
|
||||||
|
},
|
||||||
{ key: "theme", i18nKey: "config.theme", options: THEME_OPTIONS },
|
{ key: "theme", i18nKey: "config.theme", options: THEME_OPTIONS },
|
||||||
{ key: "chartColor", i18nKey: "config.chartColor", options: THEME_OPTIONS },
|
{ key: "chartColor", i18nKey: "config.chartColor", options: THEME_OPTIONS },
|
||||||
{
|
{
|
||||||
@@ -66,8 +70,16 @@ const CONFIG_FIELDS: {
|
|||||||
i18nKey: "config.fontHeading",
|
i18nKey: "config.fontHeading",
|
||||||
options: FONT_HEADING_OPTIONS,
|
options: FONT_HEADING_OPTIONS,
|
||||||
},
|
},
|
||||||
{ key: "menuAccent", i18nKey: "config.menuAccent", options: MENU_ACCENT_OPTIONS },
|
{
|
||||||
{ key: "menuColor", i18nKey: "config.menuColor", options: MENU_COLOR_OPTIONS },
|
key: "menuAccent",
|
||||||
|
i18nKey: "config.menuAccent",
|
||||||
|
options: MENU_ACCENT_OPTIONS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "menuColor",
|
||||||
|
i18nKey: "config.menuColor",
|
||||||
|
options: MENU_COLOR_OPTIONS,
|
||||||
|
},
|
||||||
{ key: "radius", i18nKey: "config.radius", options: RADIUS_OPTIONS },
|
{ key: "radius", i18nKey: "config.radius", options: RADIUS_OPTIONS },
|
||||||
{ key: "template", i18nKey: "config.template", options: TEMPLATE_OPTIONS },
|
{ key: "template", i18nKey: "config.template", options: TEMPLATE_OPTIONS },
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export function FolderActions() {
|
|||||||
className="justify-start gap-2 h-9"
|
className="justify-start gap-2 h-9"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
try {
|
try {
|
||||||
await openProjectBootWindow()
|
await openProjectBootWindow("welcome")
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("[FolderActions] failed to open project boot:", err)
|
console.error("[FolderActions] failed to open project boot:", err)
|
||||||
toast.error(t("toasts.openProjectBootFailed"))
|
toast.error(t("toasts.openProjectBootFailed"))
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "مجلد",
|
"fallbackFolderName": "مجلد",
|
||||||
"openFolder": "فتح مجلد",
|
"openFolder": "فتح مجلد",
|
||||||
"cloneRepository": "استنساخ المستودع",
|
"cloneRepository": "استنساخ المستودع",
|
||||||
|
"projectBoot": "مُنشئ المشروع",
|
||||||
"opened": "مفتوح",
|
"opened": "مفتوح",
|
||||||
"recentOpen": "المفتوح مؤخرًا"
|
"recentOpen": "المفتوح مؤخرًا"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "Ordner",
|
"fallbackFolderName": "Ordner",
|
||||||
"openFolder": "Ordner öffnen",
|
"openFolder": "Ordner öffnen",
|
||||||
"cloneRepository": "Repository klonen",
|
"cloneRepository": "Repository klonen",
|
||||||
|
"projectBoot": "Projekt-Boot",
|
||||||
"opened": "Geöffnet",
|
"opened": "Geöffnet",
|
||||||
"recentOpen": "Zuletzt geöffnet"
|
"recentOpen": "Zuletzt geöffnet"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "Folder",
|
"fallbackFolderName": "Folder",
|
||||||
"openFolder": "Open Folder",
|
"openFolder": "Open Folder",
|
||||||
"cloneRepository": "Clone Repository",
|
"cloneRepository": "Clone Repository",
|
||||||
|
"projectBoot": "Project Boot",
|
||||||
"opened": "Opened",
|
"opened": "Opened",
|
||||||
"recentOpen": "Recently Opened"
|
"recentOpen": "Recently Opened"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "Carpeta",
|
"fallbackFolderName": "Carpeta",
|
||||||
"openFolder": "Abrir carpeta",
|
"openFolder": "Abrir carpeta",
|
||||||
"cloneRepository": "Clonar repositorio",
|
"cloneRepository": "Clonar repositorio",
|
||||||
|
"projectBoot": "Inicializador de proyecto",
|
||||||
"opened": "Abierto",
|
"opened": "Abierto",
|
||||||
"recentOpen": "Abiertos recientemente"
|
"recentOpen": "Abiertos recientemente"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "Dossier",
|
"fallbackFolderName": "Dossier",
|
||||||
"openFolder": "Ouvrir le dossier",
|
"openFolder": "Ouvrir le dossier",
|
||||||
"cloneRepository": "Cloner le dépôt",
|
"cloneRepository": "Cloner le dépôt",
|
||||||
|
"projectBoot": "Lanceur de projet",
|
||||||
"opened": "Ouvert",
|
"opened": "Ouvert",
|
||||||
"recentOpen": "Ouvert récemment"
|
"recentOpen": "Ouvert récemment"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "フォルダ",
|
"fallbackFolderName": "フォルダ",
|
||||||
"openFolder": "フォルダを開く",
|
"openFolder": "フォルダを開く",
|
||||||
"cloneRepository": "リポジトリをクローン",
|
"cloneRepository": "リポジトリをクローン",
|
||||||
|
"projectBoot": "プロジェクトブート",
|
||||||
"opened": "開いているフォルダ",
|
"opened": "開いているフォルダ",
|
||||||
"recentOpen": "最近開いたフォルダ"
|
"recentOpen": "最近開いたフォルダ"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "폴더",
|
"fallbackFolderName": "폴더",
|
||||||
"openFolder": "폴더 열기",
|
"openFolder": "폴더 열기",
|
||||||
"cloneRepository": "리포지토리 클론",
|
"cloneRepository": "리포지토리 클론",
|
||||||
|
"projectBoot": "프로젝트 부트",
|
||||||
"opened": "열린 항목",
|
"opened": "열린 항목",
|
||||||
"recentOpen": "최근 연 항목"
|
"recentOpen": "최근 연 항목"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "Pasta",
|
"fallbackFolderName": "Pasta",
|
||||||
"openFolder": "Abrir pasta",
|
"openFolder": "Abrir pasta",
|
||||||
"cloneRepository": "Clonar repositório",
|
"cloneRepository": "Clonar repositório",
|
||||||
|
"projectBoot": "Inicializador de projeto",
|
||||||
"opened": "Aberto",
|
"opened": "Aberto",
|
||||||
"recentOpen": "Abertos recentemente"
|
"recentOpen": "Abertos recentemente"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "文件夹",
|
"fallbackFolderName": "文件夹",
|
||||||
"openFolder": "打开文件夹",
|
"openFolder": "打开文件夹",
|
||||||
"cloneRepository": "克隆仓库",
|
"cloneRepository": "克隆仓库",
|
||||||
|
"projectBoot": "项目启动器",
|
||||||
"opened": "已打开",
|
"opened": "已打开",
|
||||||
"recentOpen": "最近打开"
|
"recentOpen": "最近打开"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -856,6 +856,7 @@
|
|||||||
"fallbackFolderName": "資料夾",
|
"fallbackFolderName": "資料夾",
|
||||||
"openFolder": "打開資料夾",
|
"openFolder": "打開資料夾",
|
||||||
"cloneRepository": "複製倉庫",
|
"cloneRepository": "複製倉庫",
|
||||||
|
"projectBoot": "專案啟動器",
|
||||||
"opened": "已打開",
|
"opened": "已打開",
|
||||||
"recentOpen": "最近打開"
|
"recentOpen": "最近打開"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -952,9 +952,9 @@ export async function openSettingsWindow(
|
|||||||
window.open(result.path, `settings-${section ?? "general"}`)
|
window.open(result.path, `settings-${section ?? "general"}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function openProjectBootWindow(): Promise<void> {
|
export async function openProjectBootWindow(source?: string): Promise<void> {
|
||||||
if (getTransport().isDesktop()) {
|
if (getTransport().isDesktop()) {
|
||||||
return getTransport().call("open_project_boot_window")
|
return getTransport().call("open_project_boot_window", { source })
|
||||||
}
|
}
|
||||||
window.open("/project-boot", "project-boot")
|
window.open("/project-boot", "project-boot")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user