22ce93d
commit 22ce93d
6 files changed
+111 -39
Showing 6 changed files+111-39
▼app.html
+14-0
| @@ -0,0 +1,14 @@ | ||
1 | +<!DOCTYPE html> | |
2 | +<html lang="en"> | |
3 | + <head> | |
4 | + <meta charset="UTF-8" /> | |
5 | + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
6 | + <title>Linuxy</title> | |
7 | + <meta name="description" content="Linuxy - One-Click Linux Application Manager" /> | |
8 | + <link rel="icon" type="image/png" href="/assets/linuxy-icon.png" /> | |
9 | + </head> | |
10 | + <body> | |
11 | + <div id="root"></div> | |
12 | + <script type="module" src="/src/main.tsx"></script> | |
13 | + </body> | |
14 | +</html> | |
0 | 15 | |
▼src/App.tsx
+15-5
| @@ -129,12 +129,22 @@ function App() { | ||
129 | 129 | |
130 | 130 | const unlistenDetected = listen<string>("appimage-detected", (event) => { |
131 | 131 | const fullPath = event.payload; |
132 | + const ignored = JSON.parse(localStorage.getItem('ignoredAppImages') || '[]'); | |
133 | + if (ignored.includes(fullPath)) return; | |
134 | + | |
132 | 135 | const fileName = fullPath.split("/").pop() || fullPath; |
133 | 136 | setModal({ |
134 | 137 | title: "Install Detected AppImage", |
135 | 138 | message: `New AppImage detected:\n${fileName}\n\nInstall it to your library?`, |
136 | 139 | actions: [ |
137 | - { label: "Later", variant: "secondary" }, | |
140 | + { | |
141 | + label: "Later", | |
142 | + variant: "secondary", | |
143 | + onClick: () => { | |
144 | + ignored.push(fullPath); | |
145 | + localStorage.setItem('ignoredAppImages', JSON.stringify(ignored)); | |
146 | + } | |
147 | + }, | |
138 | 148 | { |
139 | 149 | label: "Install", |
140 | 150 | variant: "primary", |
| @@ -529,8 +539,8 @@ function App() { | ||
529 | 539 | marginTop: "10px", |
530 | 540 | padding: "10px", |
531 | 541 | background: firejailInstalled |
532 | - ? "rgba(76, 175, 80, 0.1)" | |
533 | - : "rgba(244, 67, 54, 0.1)", | |
542 | + ? "var(--accent-bg)" | |
543 | + : "var(--danger-bg)", | |
534 | 544 | borderRadius: "6px", |
535 | 545 | }} |
536 | 546 | > |
| @@ -579,8 +589,8 @@ function App() { | ||
579 | 589 | marginTop: "10px", |
580 | 590 | padding: "10px", |
581 | 591 | background: updateToolInstalled |
582 | - ? "rgba(76, 175, 80, 0.1)" | |
583 | - : "rgba(244, 67, 54, 0.1)", | |
592 | + ? "var(--accent-bg)" | |
593 | + : "var(--danger-bg)", | |
584 | 594 | borderRadius: "6px", |
585 | 595 | }} |
586 | 596 | > |
587 | 597 | |
▼src/components/AppGrid.tsx
+4-3
| @@ -55,14 +55,15 @@ const AppGrid: React.FC<AppGridProps> = ({ | ||
55 | 55 | key={app.path} |
56 | 56 | style={{ |
57 | 57 | background: "var(--bg-card)", |
58 | - borderRadius: "8px", | |
59 | - padding: "15px", | |
58 | + borderRadius: "12px", | |
59 | + padding: "20px 15px", | |
60 | 60 | display: "flex", |
61 | 61 | flexDirection: "column", |
62 | 62 | alignItems: "center", |
63 | 63 | position: "relative", |
64 | 64 | border: "1px solid var(--border-color)", |
65 | - transition: "background-color 0.3s, border-color 0.3s", | |
65 | + boxShadow: "var(--shadow-card)", | |
66 | + transition: "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)", | |
66 | 67 | }} |
67 | 68 | > |
68 | 69 | <button |
69 | 70 | |
▼src/components/Sidebar.tsx
+10-4
| @@ -35,7 +35,9 @@ const Sidebar: React.FC<SidebarProps> = ({ currentView, onViewChange, onRefresh | ||
35 | 35 | <button |
36 | 36 | style={{ |
37 | 37 | ...btnStyle, |
38 | - background: currentView === "library" ? "rgba(255, 255, 255, 0.1)" : "transparent", | |
38 | + background: currentView === "library" ? "var(--accent-bg)" : "transparent", | |
39 | + color: currentView === "library" ? "var(--accent-color)" : "var(--text-secondary)", | |
40 | + borderRight: currentView === "library" ? "3px solid var(--accent-color)" : "3px solid transparent", | |
39 | 41 | }} |
40 | 42 | onClick={() => onViewChange("library")} |
41 | 43 | > |
| @@ -45,7 +47,9 @@ const Sidebar: React.FC<SidebarProps> = ({ currentView, onViewChange, onRefresh | ||
45 | 47 | <button |
46 | 48 | style={{ |
47 | 49 | ...btnStyle, |
48 | - background: currentView === "discover" ? "rgba(255, 255, 255, 0.1)" : "transparent", | |
50 | + background: currentView === "discover" ? "var(--accent-bg)" : "transparent", | |
51 | + color: currentView === "discover" ? "var(--accent-color)" : "var(--text-secondary)", | |
52 | + borderRight: currentView === "discover" ? "3px solid var(--accent-color)" : "3px solid transparent", | |
49 | 53 | }} |
50 | 54 | onClick={() => onViewChange("discover")} |
51 | 55 | > |
| @@ -55,7 +59,9 @@ const Sidebar: React.FC<SidebarProps> = ({ currentView, onViewChange, onRefresh | ||
55 | 59 | <button |
56 | 60 | style={{ |
57 | 61 | ...btnStyle, |
58 | - background: currentView === "settings" ? "rgba(255, 255, 255, 0.1)" : "transparent", | |
62 | + background: currentView === "settings" ? "var(--accent-bg)" : "transparent", | |
63 | + color: currentView === "settings" ? "var(--accent-color)" : "var(--text-secondary)", | |
64 | + borderRight: currentView === "settings" ? "3px solid var(--accent-color)" : "3px solid transparent", | |
59 | 65 | }} |
60 | 66 | onClick={() => onViewChange("settings")} |
61 | 67 | > |
| @@ -64,7 +70,7 @@ const Sidebar: React.FC<SidebarProps> = ({ currentView, onViewChange, onRefresh | ||
64 | 70 | |
65 | 71 | <div style={{ flex: 1 }} /> |
66 | 72 | |
67 | - <button style={{ ...btnStyle, background: "transparent" }} onClick={onRefresh}> | |
73 | + <button style={{ ...btnStyle, background: "transparent", color: "var(--text-secondary)", borderRight: "3px solid transparent" }} onClick={onRefresh}> | |
68 | 74 | <RefreshCw size={18} style={{ marginRight: 10 }} /> Refresh |
69 | 75 | </button> |
70 | 76 | </div> |
71 | 77 | |
▼src/styles/main.css
+54-27
| @@ -1,31 +1,47 @@ | ||
1 | 1 | :root { |
2 | - --bg-main: #121212; | |
3 | - --bg-sidebar: #1e1e1e; | |
4 | - --bg-card: #252525; | |
5 | - --bg-input: #1a1a1a; | |
6 | - --text-primary: #ffffff; | |
7 | - --text-secondary: #aaaaaa; | |
8 | - --text-muted: #888888; | |
9 | - --border-color: #333333; | |
10 | - --accent-color: #4caf50; | |
11 | - --accent-hover: #45a049; | |
12 | - --danger-color: #f44336; | |
13 | - --info-color: #2196f3; | |
2 | + /* Elegant Dark Theme Palette (Deep Charcoal/Blue hue) */ | |
3 | + --bg-main: hsl(224, 15%, 8%); | |
4 | + --bg-sidebar: hsl(224, 15%, 11%); | |
5 | + --bg-card: hsl(224, 14%, 13%); | |
6 | + --bg-input: hsl(224, 14%, 16%); | |
7 | + --text-primary: hsl(220, 20%, 96%); | |
8 | + --text-secondary: hsl(220, 15%, 75%); | |
9 | + --text-muted: hsl(220, 15%, 55%); | |
10 | + --border-color: hsl(224, 15%, 20%); | |
11 | + | |
12 | + /* Vibrant Accents */ | |
13 | + --accent-color: hsl(145, 65%, 45%); | |
14 | + --accent-hover: hsl(145, 65%, 52%); | |
15 | + --danger-color: hsl(0, 85%, 65%); | |
16 | + --info-color: hsl(210, 100%, 65%); | |
17 | + | |
18 | + /* Translucent Backgrounds for Alerts */ | |
19 | + --accent-bg: hsla(145, 65%, 45%, 0.15); | |
20 | + --danger-bg: hsla(0, 85%, 65%, 0.15); | |
21 | + | |
22 | + --shadow-card: 0 8px 30px rgba(0, 0, 0, 0.4); | |
14 | 23 | } |
15 | 24 | |
16 | 25 | [data-theme="light"] { |
17 | - --bg-main: #f5f5f5; | |
18 | - --bg-sidebar: #ffffff; | |
26 | + /* Crisp Light Theme Palette */ | |
27 | + --bg-main: hsl(220, 15%, 98%); | |
28 | + --bg-sidebar: hsl(220, 15%, 95%); | |
19 | 29 | --bg-card: #ffffff; |
20 | - --bg-input: #eeeeee; | |
21 | - --text-primary: #121212; | |
22 | - --text-secondary: #555555; | |
23 | - --text-muted: #888888; | |
24 | - --border-color: #dddddd; | |
25 | - --accent-color: #2e7d32; | |
26 | - --accent-hover: #1b5e20; | |
27 | - --danger-color: #d32f2f; | |
28 | - --info-color: #1976d2; | |
30 | + --bg-input: hsl(220, 10%, 90%); | |
31 | + --text-primary: hsl(220, 20%, 15%); | |
32 | + --text-secondary: hsl(220, 15%, 35%); | |
33 | + --text-muted: hsl(220, 10%, 50%); | |
34 | + --border-color: hsl(220, 10%, 85%); | |
35 | + | |
36 | + --accent-color: hsl(150, 75%, 35%); | |
37 | + --accent-hover: hsl(150, 75%, 42%); | |
38 | + --danger-color: hsl(0, 75%, 45%); | |
39 | + --info-color: hsl(210, 85%, 45%); | |
40 | + | |
41 | + --accent-bg: hsla(150, 75%, 35%, 0.1); | |
42 | + --danger-bg: hsla(0, 75%, 45%, 0.08); | |
43 | + | |
44 | + --shadow-card: 0 8px 30px rgba(0, 0, 0, 0.05); | |
29 | 45 | } |
30 | 46 | |
31 | 47 | * { |
| @@ -39,10 +55,11 @@ body { | ||
39 | 55 | overflow: hidden; |
40 | 56 | background-color: var(--bg-main); |
41 | 57 | color: var(--text-primary); |
42 | - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; | |
43 | - transition: | |
44 | - background-color 0.3s, | |
45 | - color 0.3s; | |
58 | + /* Use a premium, modern font stack */ | |
59 | + font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; | |
60 | + transition: background-color 0.4s ease, color 0.4s ease; | |
61 | + -webkit-font-smoothing: antialiased; | |
62 | + -moz-osx-font-smoothing: grayscale; | |
46 | 63 | } |
47 | 64 | |
48 | 65 | #root { |
| @@ -53,6 +70,16 @@ body { | ||
53 | 70 | |
54 | 71 | button { |
55 | 72 | font-family: inherit; |
73 | + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); | |
74 | +} | |
75 | + | |
76 | +button:hover:not(:disabled) { | |
77 | + transform: translateY(-1px); | |
78 | + filter: brightness(1.1); | |
79 | +} | |
80 | + | |
81 | +button:active:not(:disabled) { | |
82 | + transform: translateY(1px); | |
56 | 83 | } |
57 | 84 | |
58 | 85 | input { |
59 | 86 | |
▼vite.config.ts
+14-0
| @@ -9,9 +9,23 @@ export default defineConfig({ | ||
9 | 9 | strictPort: true, |
10 | 10 | }, |
11 | 11 | envPrefix: ["VITE_", "TAURI_"], |
12 | + base: "./", | |
12 | 13 | build: { |
13 | 14 | target: process.env.TAURI_PLATFORM == "windows" ? "chrome105" : "safari13", |
14 | 15 | minify: !process.env.TAURI_DEBUG ? "esbuild" : false, |
15 | 16 | sourcemap: !!process.env.TAURI_DEBUG, |
17 | + rollupOptions: { | |
18 | + input: { | |
19 | + index: "./index.html", | |
20 | + app: "./app.html", | |
21 | + }, | |
22 | + output: { | |
23 | + entryFileNames: "assets/[name]-[hash].js", | |
24 | + chunkFileNames: "assets/[name]-[hash].js", | |
25 | + assetFileNames: "assets/[name]-[hash].[ext]", | |
26 | + }, | |
27 | + }, | |
28 | + outDir: "dist", | |
29 | + emptyOutDir: true, | |
16 | 30 | }, |
17 | 31 | }); |
18 | 32 | |